Click here to Skip to main content
14,930,024 members
Articles / Programming Languages / C#
Article
Posted 24 Sep 2019

Tagged as

Stats

18.1K views
819 downloads
22 bookmarked

Creative Writer's Word-Processor

Rate me:
Please Sign up or sign in to vote.
4.94/5 (23 votes)
12 Jun 2021CPOL27 min read
A tool for writers
In this article, you will learn about a word-processor that makes use of multiple dictionaries, pop-up definitions and colorful interactive multi-button picturebox expedited with a swift Sweep And Prune algorithm.

Part I: How I Scraped Merriam-Webster's Dictionary

Part II: Merriam-Webster's Dictionary: Converting HTML to RTF

Zipped Dictionary Files

Introduction


Update: 2019/11/15 - Found and fixed a few bugs - updated source code

Update: 2019/11/16 - Added more search feedback & fixed some bugs - updated source code

Update: 2020/01/23 - Added new GUI FileDialog - fixed some DictionarySelection bugs - updated source code

Update: 2021/01/30 - Fixed a 'Spell Check' crash, added hover-time delay feature, new Irish-English Dictionary

Update: 2021/04/24 - changed Dictionary Output form - built in-house toolbar/ruler/menu in text editing area - changes fast-key combination

Update: 2021/05/21 - debugged/improved Dictionary output - changed Notes to RTF files - Highlighter Color selection

Update: 2021/05/24 - tinkered - no major changes fixed pesky bug in Dictionary Output

Update: 2021/05/13 - too many updates and this article just needs to be rewritten... i know.  but I'm writing full-time and using this project everyday : finding, debuggin & fixing minor details. 

  1. if you haven't notice : there hasn't been a spell-check since Hunspell declared war on me sometime last year.   
  2. the dictionary searches are now 'boolean AND functional', by that I mean you can search 'gemstone red' in a context search and find all the files that have both those words in their definitions(it used to chop off all the words but the first).  This, however, does create an issue when you've left the 'clipboard' search option on and cut/paste entire swaths of your text... it will search a long, long ... long time for an entry that has all those words in it if you don't abort your unintended search by right-click'ing context-menu 'abort search' on the 'Crass' Image 1 spinning search-ing icon. 
  3. The dictionary text now has the 'right-click mouse' option added to the pop-up definition time-delays. 
    • Left click a word in the definition tells the app to 'search the same dictionary this definition came from for the word i just clicked'
    • Right-click means 'pop-up definition of the word i just clicked'. 
  4. The '!' button in the dictionary definition area is a toggle 'Top Most'.  This means that the Dictionary form will be either 'top most' - as in always on top of all other forms in your work space.  or ... not.
  5. from the main writing area : there are new key controls for the Dictionary form
    • the searches are now launched using the Ctrl-Shift + 'char' key combination
    • there are several new Ctrl-Alt controls
      • Ctrl-Alt-Z scroll down search results list
      • Ctrl-Alt-A scroll up search results list
      • Ctrl-Alt-Q is equivalent to the '^' button on the Dictionary form which creates a text display box copy of the current search result displayed on that form
      • Ctrl-Alt-X clears the list of 'copy' boxes beneath the main definition

sorry for this article being such a mess... I'll clean it up and rewrite the entire thing when I'm done writing my next novel (probably in the New Year).

 


 

I'm a writer. I write. Most of the time, I write software but every so often, I need to change speed and write a story, or even a novel. Anyone can use commercially available word-processors and do very well. I'm willing to guess that not many authors, aside from the independently-destitute like myself, build & test their own word-processors. Few spend weeks and months typing dictionaries into databases to incorporate them into their writing tools and none post articles about how they scraped Merriam-Webster's website to complement their hacking skills with a bit of prose.

What you're reading here today is the result of all that.

Background

Back when WiFi was not freely available in soup kitchens, internet cafés charged good coin to let you see the marvels of the information super-highway and librarians shushed you off after only one hour of working at a dusty old CRT screen chugging along their slow and overcrowded pipe, so scraping non-existing online dictionaries was a thing of fantasy. Word processors could spell check but getting a definition required leafing through a heavy book at the frightening peril of getting a paper-cut. So, if you wanted a word-processor to include a dictionary, you either packed your CD-ROM with what you could afford and wobbled from one app to the other while trying not to crash your 30MHz 386, or you just looked it up in grandpa's big-word book. Unless you were hardcore enough to borrow a dictionary from the library and renewed it every three weeks while you typed each word entry into your PC, then saved them onto your crowded harddrive. Yes, yes, I think the word hardcore is appropriate, otherwise I'd have to resort to self-abusive language unsuitable for the non-TOR tip of the internet.

So, if you've read my previous article, Spell Weller but Grammar's Up to You, then you're probably aware of my affinity for spending 100s of hours, typing dictionary after dictionary, day-in & day-out, into my computer. It took me only six weeks to type the mediocre volume: Webster's New Explorer Dictionary and six months to type the Larousse Dictionnaire du Français d'aujourd'hui French Dictionary (for which I made an app that conjugates, "bien sur" ... an app which I have since lost and will have to re-write). A dozen dictionaries and hundreds of typos later, I give them all to you, dear reader, for free. Just go to the web-link above to access them off my GoogleDrive.

Update: 2021/01/30 - I've recently scraped an Irish-English Dictionary off a government of Ireland website that is free of advertisement and is intended to promote the Gaelic language. It is now available off my Google Drive.

Since the app auto-detects the dictionary files and directories, you have to put them where it expects to find them. Right now, it's hard-coded to search for the C:\Words_Dictionaries\ directory on your C: drive, then detect all the sub-directories that end in the four-letters "Dict". This distinction is hard-wired in the code below but is no longer necessary and can be removed so long as you don't put other sub-directories in with the Dictionaries you just downloaded.

C#
public classBinTrees()
{
    instance = this;
    new formBinSearchResults_();

    string strSearchPattern = "*dict";
    if (!System.IO.Directory.Exists(strDictionaries_SourceDirectory))
        System.IO.Directory.CreateDirectory(strDictionaries_SourceDirectory);
    {
    // code excised for brevity
    }
    bck_BuildBinSearch_Init();            // initialize background worker 
                                          // to detect new dictionaries 
    if (bolRebuildDictionary)             // if new dictionary sub-dir is found -> build 
                                          // its search-engine data-set
        bck_BuildBinSearch.RunWorkerAsync();
}

Create the C:\Words_Dictionaries\ directory. Download all the zipped files stored on my GoogleDrive and expand the zipped files into c:\Words_Dictionaries\ so that when you're done, it should look something like this:

Image 2

Note to the Newbie

For those of you who wandered in here without a clue as to how to run a C# application, don't worry. It's a simple matter.

  1. Download the source code and extract it from the .zip file somewhere you'll know where to find it.
  2. Download Visual Studio 2019 from Microsoft and follow the instructions to install that essential Software Development Kit (SDK).
  3. Double click the fancy new icon that appears on your desktop.
  4. Select the 'open solution' button when prompted - or use the file-menu to open a 'solution'.
  5. Find the source-code you downloaded.
  6. Select the words.sln file and press ok.
  7. When it's loaded, you can
    • run the app in debugger-mode (slightly slower than the executable) by pressing F5
    • or, compile the application by pressing the Ctrl-Shift-B key-combination and then find the executable in the source-code's subdirectory c:/WhereverYouPutTheSourceCode/Bin/Debug/words.exe

The source code on offer here today for the low-low price of zip-nothing is the word-processor I wrote ten years ago that I used to write my fourth novel Cleats of the Counter-Revolution. I've worked on this app considerably since then and it's looking pretty good. It makes use of EXTENDED Version of Extended Rich Text Box (which helped it a lot), as well as a search engine for multiple dictionaries you can combine at will and an intuitive notes form to help you organize the tangled underbrush beneath your creative muse.

Update: 2021/01/30: I only just noticed that the EXTENDED Version of Extended Rich Text Box was crashing when I tried to use its integrated Spell-Checker (it took me so long to notice because I never use it) so I added the requisite DIC files to fix this issue. You'll need to download these files and extract them in your /bin/debug/ as shown below:

Image 3

The only new source-code widget that might interest you is a classMultiButtonPic that inherits a PictureBox and can paint hundreds of interactive buttons using a sweep-and-prune algorithm to map them all. I've improved it since my previous article so if you already have a copy, you'll want the newer one.

Using the Code

This is a functioning app on its own, but we might as well have a look at that famous classMultiButtonPic mentioned above. It's essentially a picture box with rectangles mapped out onto it that your user can interact with using the mouse cursor.

Image 4

Everything beneath the 'add' & 'hide' buttons (except the textbox with the 'W') are buttons drawn on a common picture box. The Ctrl 'button' is the only one that doesn't interact. The rows of four '¤' set the selected search style for each dictionary. There are also three buttons at the bottom 'Use Clip Board', 'Pop Up Reference' & 'Delete'. The response time is great. Each button can be set to toggle independently from the others and the widget's internal mouse events can be overwritten in order to use these buttons like they were radio-buttons on a common panel.

Here's the Mouse-click event inside the multi-button:

C#
//

MouseEventHandler _eventHandler_MouseClick;
public MouseEventHandler eventHandler_MouseClick
{
  get { return _eventHandler_MouseClick; }
  set
  {
    if (_eventHandler_MouseClick != value)
    {
      if (_eventHandler_MouseClick != null)
        MouseClick -= _eventHandler_MouseClick;
      MouseClick -= Event_MouseClick;

      _eventHandler_MouseClick = value;
            
      if (_eventHandler_MouseClick != null)
        MouseClick += _eventHandler_MouseClick;
      else
        MouseClick += Event_MouseClick;
    }
  }
}

virtual public void Event_MouseClick(object sender, MouseEventArgs e)
{
  if (cButtonUnderMouse != null)
  {
    if (cButtonUnderMouse.CanBeToggled)
      cButtonUnderMouse.Toggle();
  }
}
//

by setting the MBP (instance of a classMultiButtonPic) _eventHandler_MouseClick to an event in your app, that event will override the MBP's mouse click event. Here's how it happens in this app:

The event is set in the panelSelectDictionary class:

C#
//
cMBP.eventHandler_MouseClick = cMBP_HTMLTagList_Click;
//

Then the event itself takes over the job of toggling what needs to be toggled in order for groups of buttons to be mutually exclusively toggled (like radio-buttons on a common panel) in the case of the search-type rows of buttons next to the names of the dictionaries.

C#
//

private void cMBP_HTMLTagList_Click(object sender, EventArgs e)
{
classCK_Objects.classMultiButtonPic cMBPSender = (classCK_Objects.classMultiButtonPic)sender;
classCK_Objects.classMultiButtonPic.classButton cBtn = 
   (classCK_Objects.classMultiButtonPic.classButton)cMBPSender.cButtonUnderMouse;
if (cBtn != null)
{
  if (cBtn.Tag != null)
  {
    classButtonArray cBtnArray = (classButtonArray)cBtn.Tag;
    classBinTrees.classDictionary cDictionary = cBtnArray.cDictionary;
    int intIndex = cBtnArray.lstButtons.IndexOf(cBtn);
    if (intIndex < (int)enuSearchType._num)
    {
      cBtnArray.eSearchType = (intIndex >= 0 && intIndex < (int)enuSearchType._num)
                        ? (enuSearchType)intIndex
                        : enuSearchType._num;
      for (int intBtnCounter = 0; 
                intBtnCounter < (int)enuSearchType._num; intBtnCounter++)
      {
        cBtn = cBtnArray.lstButtons[intBtnCounter];
        cBtn.Toggled
            = cBtn.Highlight
            = intBtnCounter == intIndex;
      }
      cMBPSender.Refresh();
      if (cBtnPopupReference.Toggled)
        formDictionarySelection.instance.pnlPopUpReference = this;
    }
  }
  else
  {
    panelSelector.enuTypeButton eButtonType = (panelSelector.enuTypeButton)cBtn.obj;
    switch (eButtonType)
    {
      case panelSelector.enuTypeButton.UseClipBoard:
        {
          cBtn.Toggle();
          if (cBtn.Toggled)
          {
            for (int intPnlCounter = 0; intPnlCounter < 
                       formDictionarySelection.instance.lstPnlSelector.Count; intPnlCounter++)
            {
              panelSelector pnlSel = 
                           formDictionarySelection.instance.lstPnlSelector[intPnlCounter];
              if (pnlSel != this && pnlSel.cBtnUseClipBoard.Toggled)
              {
                pnlSel.cBtnUseClipBoard.Toggled = false;
                pnlSel.cBtnUseClipBoard.Highlight = false;
                pnlSel.cMBP.Refresh();
              }
            }
            formDictionarySelection.instance.pnlUseClipBoard = this;
          }
          else
          {
            formDictionarySelection.instance.pnlUseClipBoard = null;
          }
          formDictionarySelection.instance.TmrClipboard_Set();
        }
        break;

// some cases deleted for brevity

      default:
        {
        }
        break;
    }
  }
}

//

In the case of the UseClipBoard button, it needs to look at other panels to make certain that no two panels list dictionaries to be searched whenever your user copies text onto the MS clipboard (which is convenient for use outside this word-processor, e.g., while in your web-browser).

Below, you can see the Dictionary Selection screen. By clicking the 'add' button on top, you can add new panels with a full list of all available dictionaries to select from. These panels each have their own Fast-key selections, as well as the option to be selected as the ClipBoard search or PopUpReference dictionaries. Note the top-middle panel's fast-key is Ctrl-T and has the Thesaurus : English dictionary selected. So, when you have your cursor on a word, pressing Ctrl-T

Update: 2021/01/30: Since many of the editing functions in the EXTENDED Version of Extended Rich Text Box rely on the control key, e.g., Ctrl-X & Ctrl-C, I've changed the dictionary fast-key from Ctrl-[user selected char] to Ctrl-Alt-[user selected char] and in this way, made all 26 letters (actually the letters C, E, R & T produce these character ©€®™ respectively when combined with Ctrl-Alt. So that limits you to 22 letters) of the alphabet + 10 numerals available as dictionary control fast-keys.

Update: 2021/04/24: I built my own Rich Text Box with many of the features that were found in the Extended Version of Extended Rich Text Box - the code is in file ck_RichTextBox and is included in the build.

Pressing Ctrl-Alt-T in the App will summon the search results of the English Thesaurus for whatever word your cursor is on. Ctrl-Alt-W will search Merriam-Webster's dictionary, as it is set in the top-left panel below.

Update : 2021/04/24 : I changed the Ctrl-Alt + Fast-Char combination which the user programs to Ctrl-Shift + Fast-Char because I don't play the piano and feel its easier to use.  Doh, ra, me.

N.B. If you want the search type selection to stand out more than they do in the image below, you can go to the class panelSelector panelSelector() instantiation function and add the line:

C#
//
cButton.BackgroundStyle = 
   classCK_Objects.classMultiButtonPic.classButton.enuBackgroundStyle.BlendIdle;
//

to the default case of the switch(eSearchType). BackgroundStyle = Blend will blend the button with the background image when that button is either idle or highlighted (mouse-over or toggled on) while the BlendIdle setting will not blend with the background when it is highlighted, which is what you want.

Image 5

In the code above this image, you can see the Switch-Case where the UseClipBoard is dealt with. Since we only want one of the many panels to be referenced when the user copies text to the MS-Clipboard, we have to override the click Mouse-Event and manually set and unset all the UseClipBoard buttons for each of the MultiButtonPics on the screen in order for them to be mutually exclusive. They work similar to the Search-Type selection buttons mentioned earlier, except that they're on different MBP objects and can be toggled on/off. Unlike a set of radio buttons, where you can click the same already selected button again but cannot toggle it off.

N.B. If you plan to use the Rhyming Dictionary, you'll have to set its search-type to 'content' and not 'heading' because I was annoyed watching it download the same list of 100 words 100 times for the same rhyme. So if you want to rhyme with 'log' and you get the results for 'dog', it's because the word dog appears in the list of words that rhyme with 'log' and that's just that.

Update: 2021/01/30: Pop-Up Definition delay selection

A recent change I've made to this Word-Processor is the means of setting a delay time for the pop-up definition to appear when the mouse hovers in the Dictionary Results text box. In the Dictionary Selection form shown below, there is now a new 'PopUpDelay Time' button near the top.

Image 6

When you move the mouse cursor over it, a listbox appears providing you with option settings.

Image 7

You can set the delay time required for the mouse to hover motionless over a word (in the Dictionary search result textbox) before that word's definition Pops-Up. Clicking on a word in the Dictionary Result Text Box will still launch a search for that word and the results will appear as a regular word-search but, alternately, if you selected the last option 'Ctrl Mouse Click', and you're holding down the 'Ctrl' key when you click a word, that word's definition will appear in a 'Pop-Up' window(as if it were a hover search) leaving your original search results intact rather than (if you don't hold the Ctrl button when you click on a word) generate an entirely different search and search results.

Update: 2021/01/30 - While you masticate text, champ at content or consider your verse you can peruse through your search results without letting your hand stray from the keys by using the Alt-Up & Alt-Down key combinations.

Sweep And Prune

The Sweep and Prune algorithm is implemented as its own class and can be used with any kind of objects from characters in a string (just set the Y value to a constant and use the character index as X) to a map of the cities in Britney Spears's World Tour. You create elements, define their regions and add them to the map. Then when you ask it 'what is under Point(x, y)?' it spits-up whatever you've got hiding under there. Here's a good article to help you understand the algorithm.

After receiving a classButton object, the classMultiButtonPic's AddButton() function creates a classSweepAndPrune element which it defines with the rectangular region of the new button then sets its Tag pointer to point to that same button you're defining. Given the region which this button occupies on the screen (cBtn.Area), the SweepAndPrune element will be found whenever the classMultiButton's Search is asked to find any object on its map within the button's region (defined by its location and size, here called Area).

C#
//
public void AddButton(ref classButton cBtn)
{
  classSweepAndPrune.classElement cEle = new classSweepAndPrune.classElement();
  cEle.obj = (object)cBtn;
  cEle.rec = cBtn.Area;
  cMap.Add(ref cEle);
  cBtn.cEle = cEle;
  placeButtons();
}

//

Here's where the App's overriding Mouse-event handles a mouse-click in panelSelector class:

C#
//

private void cMBP_HTMLTagList_Click(object sender, EventArgs e)
{
  classCK_Objects.classMultiButtonPic cMBPSender = 
                       (classCK_Objects.classMultiButtonPic)sender;
  classCK_Objects.classMultiButtonPic.classButton cBtn = 
         (classCK_Objects.classMultiButtonPic.classButton)cMBPSender.cButtonUnderMouse;
  if (cBtn != null)
  {
    if (cBtn.Tag != null)
    {
      classButtonArray cBtnArray = (classButtonArray)cBtn.Tag;
      classBinTrees.classDictionary cDictionary = cBtnArray.cDictionary;
      int intIndex = cBtnArray.lstButtons.IndexOf(cBtn);
      if (intIndex < (int)enuSearchType._num)
      {
        cBtnArray.eSearchType = (intIndex >= 0 && intIndex < (int)enuSearchType._num)
                          ? (enuSearchType)intIndex
                          : enuSearchType._num;
        for (int intBtnCounter = 0; 
                    intBtnCounter < (int)enuSearchType._num; intBtnCounter++)
        {
          cBtn = cBtnArray.lstButtons[intBtnCounter];
          cBtn.Toggled
              = cBtn.Highlight
              = intBtnCounter == intIndex;
        }
        cMBPSender.Refresh();
        if (cBtnPopupReference.Toggled)
          formDictionarySelection.instance.pnlPopUpReference = this;
      }
    }
//

You can see how it unpacks the classMultiButtonPic object, then retrieves the classButton which is under the mouse cursor before toggling it while untoggling all the other buttons that are stored in the same classButton array.

Update: 20210424 - The SPObjects.cs file and the Sweep & Prune objects have gone through some changes recently.  the TextBox is still only a single line and will likely perpetually be that embarassing cousin we don't talk about (or talk about too much) but I put together a TextDisplay class which is a multi-lined TextBox BUT there is no user-editing of the text... just a display screen that scrolls with the magic mouse-wheel.  I needed one of those to put together the new version of the Dictionary Display form.  I'll talk about that below

Update: 20210521 - TextDisplay had some bugs, its the object that's used to display the 'copies' of dictionary outputs into the list of smaller boxes below the Dictionary Output rtx.  It assumes the same hovering style as the hover controls for the main dictionary output richtextbox.  Handy when you have thesaurus entries listed together for different word meaning you want to match into flowing prose, let your mouse hover and whatever pop-up-dictionary you selected in the Dictionary Selection form will give you the information you're looking for.

Notes

Notes are an interesting feature because you can keep separate notes for each writing project you have. If you're plotting a novel, you might like to write out an outline before you get to the actual scribbling. Jack Kerouac could type out a novel overnight and send it to his publisher and still get paid but most of us aren't Jack Kerouac and despite his success and beep-bop prose finger-snapping rhythm, I'd still suggest : "Edit Jack! Edit!". Beatniks, what are you gonna do, right? I've only ever read one of Daniel Steele's novels, and as forgettable as it was, the one thing that struck me was the way the plot's main dilemma may have lasted throughout the entire novel but the conflicts that got us from start to finish were all resolved within a page or two, as if she just wrote it all without forethought or planning ... but I digress.

Notes... this word processor lets you keep notes. Just right click the listbox at the top to summon a context menu and you can Add, Delete or Edit the title of the note currently selected. You can edit the content of your notes by just typing what you will. You can reorder the list of notes in the listbox by selecting the one you want to move and then mouse-wheel your way up or down. For the price of forfeiting the use of the '#' pound character, you can create numerical bullet points in the content of your notes. Just type '#' and a numbered bullet will appear. Delete one, insert another or cut'n'paste them in whatever order you like and when you do the slick '#' pressing action-hero move again they'll all be reordered numerically to reflect the order in which they appear in your note's content.

Update: 20210521 - Notes Files all this has changed as of this update.  The text editing area is how the same richtextbox in the Word Processor's main editing area and each note entry is no longer a Node in an XML file but rather its own RichTextFile.  To be honest, I never use the file load/save functions in this area as the notes themselves get saved automatically in the same directory you're working in.  If you change a note's Heading using the context menu in the ListBox of the Notes region then the name of the file saved on your harddrive will be changed to match the heading of your note (with extra information to identify it to a given project).  If you edit the names of these files on your hard-drive

Image 8

then the information written in your .xml file for this writing project will no longer match the name of the RichTextFile that you wrote in your notes using the Word Processor.  In the image above the bottom file in the image is the working title of my current project.  The next file above it is the .xml file where the names of all headings in the ListBox above the text of your notes are written.  so this way, when you load your project the matching file with the same name but .xml extension gets loaded by the Notes Editor and appear in your listbox of headings.  Edit the heading = edit the filename.

I never use this stuff(Load, Save,or SaveAs) might work, might not.  I'll get around to debugging it or removing it... so they're there but I don't even remember what I had them doing because I have never used them.

You can Load, Save or SaveAs which notes you want independently from which project you're working on by using the Notes form context-menu (right-click the list of Notes Headings or Textbox below and select File).

QuickView will display the text-content of any of your notes when you move the mouse over the ListBox.

TopMost will make sure your Notes form stays in front of all other forms.

Image 9

In the image below, you can see the result of a search in Merriam-Webster's dictionary for the word 'cold'. There are 107 results and what you see is the definition for 'cold dark matter' printed out in the main dictionary output textbox below on the right while to the left of the mouse-cursor is the result of a mouse-move event over the listbox of results that puts a pop-up definition on the screen defining the word under the mouse cursor 'cold-blooded'. It's a faster way to preview what you would see appear below in the main definition output textbox below if you were to click on the listbox item over which the mouse is currently hovering.

Update: 20210424 - I made some changes to the old Dictionary Output form

Image 10

 I added SplitContainer's to the Dictionary Output form.  With one inside the other there are now 3 regions in the dictionary interface plus a button at the bottom.   so now, it looks more like this

Image 11

The first window at the top of the right side of the screen here where it says  Search(1) sparse is the listbox that contains the results of all the word-entries in the search for the word 'sparse' in the English Thesaurus(there's only the one entry).  The second window shows the content of the one file in all the Thesaurus sub-directories that contains the word 'sparse' in its heading.  These two windows ares the first panel (panel1) of both the 'main' and the 'sub' splitter where the 'sub' splitcontainer is inside the 'main' splitcontainer's panel2.  So, there remains the sub-splitter's panel2 which holds the third window which is a single PictureBox object that displays the result-copies in a list of Sweep & Prune TextDisplay objects.  These TextDisplay objects can scroll independently and, being in an SPContainer can be clustered together as much as you like(memory being your only limit).  To build this I created a User-Defined SPObject panel that displays them both on itself and each of these panels is positioned beneath its predecessor.  The SPContainer handles the main scroll-bar which is a real bonus.  This new method of doing things allows the user to click on the one Windows.Forms.Button that is on this form (the other TextDisplay kill panel buttons with the 'x's in them are SPObjects.button's drawn onto that region's Windows.Forms.PictureBox) at the bottom of the form seen straddling the left edge of the main scroll-bar.  When the user presses this button whatever is written in the 2nd (middle) box is copied into its own SPObjects.TextDisplay region in the Windows.PictureBox that fills the 3rd (bottom) region below('sub-splitter's panel2).  This way a creative-writer can load several Thesaurus entries in sequence and keep them all visible in the same region, cmpare the different word combinations together and come up with the best darned writing any country-school mar'm would be proud of.

Update: 2021/05/21 - The 'copy' definitions had bugs that didn't display the text properly.  I found some issues and fixed them.  The hover in these TextDisplay SPObjects matches the hovering settings of the Dictionary Definition window.  When you click on a word here, the definition of the word you clicked will be searched in the same dictionary from which that current definition came from.  If you copied a 'Thesaurus English' list of synonyms taken from that Thesaurus then when you click on a word in that list of synonyms then that one TextDisplay box you just clicked will either display the result of that search or not change from its current state if no result was found.  

Highlighter

You may have noticed the Image 12 on the screen.  There's a new control-box above the Rich-Text box with a big-ass exclamation on it Image 13on the far-right of the Control-Panel above the ruler.  When you click on that button (or press the handy left-slide key combination Ctrl-Shift-Z buttons together) you'll either highlight the selected text in red like that or, if you have not selected any text and the cursor is just blinking in your text-editing area, the cursor will be encased between two square brackets in red highlight Image 14.  Just type what creative-writing-editing-notes you want and they will be there in your text in red and waiting for your return with your pipe at the ready for you to re-boot 'Father Knows Best' and win yourself a Rotten Tomato.  

Update 2021/05/21 - you can now select the color you want to use when Highlighting.  The text in your project won't change color but the next time you use the Highlighter the color will be whatever you last set it to and that setting will be loaded when you quit the Word Processor and restart again.

The SPObjects class is difficult to use and far from user-friendly for the developper.  I had to fight with it to get the User-Defined panel that holds each TextDisplay to its Kill-button, but I'm sure that if I used it more often the problems that I had yesterday wouldn't occur after its use became routine.  Still, it did give me trouble... and I'm the one who conceived it and its many problems.  So, I figure anybody who's not so consanguinely attached to it would likely leave it on the vine and move on but you're free to try because it does have its advantages.

Also, the fact that they're all together on the same form on top of each other in a scrollable list makes it a lot easier to figure out what thesaurus(dictionary) entries you want to compare on the screen at the same time.  You can now click on a word in one of these SPObject.Textdisplay regions and that region's entry will then load the file of the word you clicked(should the search-engine fail to find what you're looking for the feedback wheel will disappear with no changes to the TextDisplay's appearance).  You can jump from word to word just by clicking on the word you want to see.

If you click on a word in the definition below, that word will be searched using the PopUpReference dictionary selected in the Dictionary Selection Panels. You can also let your mouse hover over a word inside that same text and get a pop-up definition that way. This can be handy when you're searching through lists of rhyming words from the Rhyming dictionary or lists of synonyms pulled out of a thesaurus. The word you're looking at in the definition may look and sound good for where you are in your creative writing but you may not be certain of its definition, having this pop-up means of quickly getting that word's definition can be a real time saver. Might spare you the embarrassment of shamelessly abusing your readers by rhyming euphoniously but not getting your meaning across, if you know what I mean.

You'll notice at the bottom right of the main dictionary definition output textbox there is a button with the '^' character on it. This allows you to make a copy of the current definition into another form you can place beside the search-results form you're looking at. Update 2021/04/24 the above section details the changes to the Dictionary Output which are now all contained on a single form not the multiple forms it used to be. That way, you can search for multiple words from a thesaurus, for example, and mix-and-match the words you think sound good together and still get your meaning across.

Update 2021/05/21 - This text editing area has now been replaced with the same kind of RichTextBox as the Word Processor's main editing area.  You do not need to worry about saving the changes you make in your notes editing.    Whenever you change heading selection in the ListBox above the Note Editor's text editing richtextbox, then the text being displayed (the previously selected note) is automatically saved to the hard-drive with the appropriate file name and the next selected note (heading in the ListBox) will be loaded from its RichTextFile and put to the screen.  see the Notes Files image above and its accompanying update notes.

Image 15

For example, in the screen capture above, you might want to talk about a 'dead moon' but not actually say 'dead moon'. So you call up a thesaurus search for the word 'dead' by putting the cursor on the word 'dead' in your text and pressing the fast-key combination Ctrl-T (n.b. as of 2021/01/30 fast-key combinations are now Ctrl-Alt- key combinations and the ctrl-alt-T combo is reserved for character, as of 2021/04/24 the key-combination is Ctrl-Shift-D ... the code has spoken. ) defined in the Dictionary Selection Screen to search for the English Thesaurus. This will bring up the Thesaurus search results for the word 'dead'. You make sure what you want is defined in the main definition textbox below by clicking it in the listbox above, then press that funny looking '^' button at the bottom of that form and a new one will appear on top of the one you just clicked. Move that form aside, scroll down your list of SPObject.TextDisplays and then repeat the search operation for the word 'moon' and you'll see the search results for that Thesaurus entry. Looking at your two thesaurus entries one above the other, you can commingle counterparts and sibilate 'lifeless satellite' or conjure 'inanimate satellite' for a sense of rhyme. Of course, you could just as well say 'dead moon'.... but whatever. You get the idea.

Points of Interest

If this project doesn't help your prose, maybe you can use some of its component parts and make something else you need. Either way, happy writing, joyous scribbling and may your documents delight, blithe belles-lettres abound that you may create contented compositions and wonder work for pleasant publications and so forth.

P.S.: Now I can go back to my Animation Editor & Sprite Editor projects because Covid-19 insists I make cartoons animation.

History

  • 2019/09/30
    1. New source files
  • 2019/09/30
    1. Fixed a bug that deleted all notes when SaveAs was used .. a bit of nuisance that one.
  • 2019/10/08
    1. Made the Notes save/load options on the Notes Context menu (you can now have the same notes for several different 'projects', e.g., different chapters of the same novel)
    2. Added Top Most form option for the Notes form (toggling on will ensure the Notes form appears in front of all other active forms in your Windows environment)
    3. Added Quick View option for the Notes ListBox (toggling on the QuickView will display the Note's text-content as you move your mouse cursor over it. To un-Toggle QuickView, either use the Notes context-menu or click on one of the listbox items.)
  • 2021/04/24
    1. added an list of SPObjects.TextDisplay's in a 3rd  box of the Dictionary-Output
    2. changed the Fast-key key-combination from Ctrl-Alt to Ctrl-Shift
    3. new RichTextBox-Ruler-Controlbar 
    4. added a highlighter button to help write editing-notes
  • 2021/05/21
    1. debugged/improved Dictionary output
    2.  changed Notes to RTF files
    3.  Highlighter Color selection

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Christ Kennedy
CEO unemployable
Canada Canada
Christ Kennedy grew up in the suburbs of Montreal and is a bilingual Quebecois with a bachelor’s degree in computer engineering from McGill University. He is unemployable and currently living in Moncton, N.B. writing his next novel.

Comments and Discussions

 
GeneralMy vote of 3 Pin
Vincent Radio25-May-21 3:37
professionalVincent Radio25-May-21 3:37 
GeneralRe: My vote of 3 Pin
Christ Kennedy25-May-21 11:31
mvaChrist Kennedy25-May-21 11:31 
PraiseMessage Closed Pin
22-May-21 7:56
MemberMember 1521159322-May-21 7:56 
Questionsubject Pin
Mohit Singh 202121-May-21 23:05
professionalMohit Singh 202121-May-21 23:05 
AnswerRe: subject Pin
Christ Kennedy22-May-21 1:44
mvaChrist Kennedy22-May-21 1:44 
QuestionObject reference not set to an instance of an object Pin
dawiemos10-Jan-20 22:30
Memberdawiemos10-Jan-20 22:30 
AnswerRe: Object reference not set to an instance of an object Pin
Christ Kennedy23-Jan-20 4:09
mvaChrist Kennedy23-Jan-20 4:09 
GeneralRe: Object reference not set to an instance of an object Pin
dawiemos29-Mar-20 20:26
Memberdawiemos29-Mar-20 20:26 
GeneralRe: Object reference not set to an instance of an object Pin
Christ Kennedy30-Jan-21 5:06
mvaChrist Kennedy30-Jan-21 5:06 
QuestionCode Critique Pin
Marc Clifton10-Oct-19 3:03
mvaMarc Clifton10-Oct-19 3:03 
AnswerRe: Code Critique Pin
Christ Kennedy11-Oct-19 4:23
mvaChrist Kennedy11-Oct-19 4:23 
Questionmail.com is blocked Pin
dawiemos26-Sep-19 9:59
Memberdawiemos26-Sep-19 9:59 
AnswerRe: mail.com is blocked Pin
Christ Kennedy26-Sep-19 22:52
mvaChrist Kennedy26-Sep-19 22:52 
QuestionMissing RHYMDICT on your server Pin
monglung25-Sep-19 10:27
professionalmonglung25-Sep-19 10:27 
AnswerRe: Missing RHYMDICT on your server Pin
Christ Kennedy25-Sep-19 15:07
mvaChrist Kennedy25-Sep-19 15:07 
GeneralRe: Missing RHYMDICT on your server Pin
monglung25-Sep-19 19:38
professionalmonglung25-Sep-19 19:38 
GeneralRe: Missing RHYMDICT on your server Pin
Christ Kennedy26-Sep-19 22:53
mvaChrist Kennedy26-Sep-19 22:53 
QuestionLooks interesting Pin
Member 1174085525-Sep-19 6:21
MemberMember 1174085525-Sep-19 6:21 
AnswerRe: Looks interesting Pin
Christ Kennedy25-Sep-19 15:16
mvaChrist Kennedy25-Sep-19 15:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.