I'm trying to create a simple text field for WYSIWYG editing. However, I only want to allow certain types of formatting (e.g. Bold, Italic, Underline and a single heading type but no colors or different fonts.)
The issue is if I use an editor that can accept formatting, someone can create or copy formatted text in another program, then simply paste it into the text field and all that formatting goes with it, allowing things I'm not interested in, such as different fonts, colors, etc. I don't want to allow that.
At best, I want to automatically strip out any formatting that I don't support. At worst, I want to simply paste whatever as plain text making them have to reformat it. But in no case do I want to just dump the clipboard to the text area.
Any thoughts on how to do this?
I would recommend creating a new text field/text area class and creating an EditPaste menu handler that (a) does what you're looking for in terms of handling the clipboard's text and (b) returns true to prevent the default pasting from happening. This is safer than using the Key down events because the user might manually select paste from the edit menu.
You can access the text on the clipboard by creating a Clipboard object.
To subclass the textfield and intercept the paste menu command:
With your Project open, go to Project Menu > Add > Class
Select the new class in the project's tab and in the properties panel set the super to TextField
Double-click on the class to edit it
Click the "Add Menu Handler" mid-toolbar button in your class
Change the menu item name to "EditPaste". Put your code in before the "return true" and be sure to leave the return true in there.
Your code can then format and paste the text manually and override the default paste function.
Any command-V or control-V in that text field will cause that menu handler to fire. Any contextual menus would be added by you anyway since real basic does not create the default contextual menus, so you'd have control over that as well.
To add the text field to a window, just change the filter above the objects list to Project controls, and drag the class in from there.
You could intercept the paste yourself by intercepting it in the KeyDown events. Then, you could look to parse it yourself. That could be kind of tricky but I think that's about the only way you could do it.
It might just be easier to parse the resulting StyleRun after the paste and strip out formatting you don't want.
Alternately, you could look at the Formatted Text Control from True North Software and override the paste methods of the control (you get all the source) and just handle it yourself.
Either way, I think it will be a fair amount of work.
Related
What I want to achieve: an easier way to edit longer text (one or two paragraphs) in a QTableWidget cell.
The problem: resizeRows wraps the text in the cell when the table is displayed. However, if I try to edit the cell, all the text appears on one line which makes it awkward to edit.
What I've tried: I tried implementing a QTextEdit widget for editing:
class EditDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
editor = super().createEditor(parent, option, index)
if isinstance(editor, QLineEdit):
textedit = QTextEdit(parent)
textedit.setPlainText(editor.text())
return textedit
That fixed the editing problem, although I have to rely on the edit box losing focus to save the text. However, after editing, the default QTableWidgetItem now shows HTML in the edited cell. I had thought that using setPlainText() would prevent this. The only text entered was "THE NOTE TEXT", seen in the middle of this screenshot:
If I then try to edit the cell again, the HTML is stripped out and just the original text ("THE NOTE TEXT") remains in the QTextEdit box until again I exit the editor.
Questions:
Is my approach a good way to implement multiline editing in a
QTableWidget?
If so, how can I get rid of the HTML markup that the
QTableWidgetItem is now displaying?
Since you only need a multiple line editor and no formatting (colors, text style, etc.) then use QPlainTextEdit.
The reason behind the returned HTML is that the default property (see the USER attribute) of QTextEdit is html: item delegates use the USER property as default to set the value of the editor and then set it back on the model, meaning that setEditorData() will behave like using setHtml() and setModelData() like toHtml().
The user property for QPlainTextEdit is just plainText, so there will be no conversion in either case.
Also note that your implementation of createEditor() will potentially raise an exception if the default editor is not a QLineEdit (if the data uses numbers or Qt dates/times), since textexit is only declared in the if, but that's a bad way to do so anyway (you're creating a widget that won't be used).
Besides, calling textedit.setPlainText(editor.text()) is useless, because at that point the editor is still empty and it will be filled only by setEditorData() (which would overwrite its contents anyway).
A more correct approach would check the data type and return the editor accordingly, then let the delegate fill the widget in its own.
def createEditor(self, parent, option, index):
if isinstance(index.data(), str):
return QTextEdit(parent)
return super().createEditor(parent, option, index)
Finally, be aware that many have tried to implement multiple line editors in item views, and very few attempts actually achieve a valid result. Many issues are related with the available item geometry, cursor navigation, UX aspects and focus management, and almost any solution has to accept some level of compromise that many users might find annoying. The most common acceptable (and less "hated") solution is to use an external editor, either shown in another part of the UI or through a dialog window.
I have an document in word, which has some fields to be filled, and an button to which I want to assign a macro. When that button is clicked, that same form with empty fields needs to be appended to the end of document, including the button (which can be clicked again and do the same thing).
Here is the document I have:
https://drive.google.com/file/d/0B_2kyqxMx5x4UkxfOHJhOGVPdnc/view?usp=sharing
The main problem with what you want to do is dynamically linking the button to the macro code to be executed. The most obvious type of button to use is the legacy ActiveX control in the Ribbon's Developer tab. But that requires its own procedure entry in the document's ThisDocument class module. While it's possible to add code to modules "on the fly" this involves disabling a security option.
A more straignt forward approach is to use the MacroButton field. This creates a clickable text within the document. It can display text or a graphic (so that it looks like a button) and is assigned the name of any public Sub that takes no parameters:
{ MACROBUTTON NameOfMacro Click here }
Ctrl+F9 to insert the field code brackets; Alt+F9 to toggle between field code and field result.
Graphics in Word 2010 and later:* The was a change to the graphics engine in Word 2010 which affects the behavior of graphics objects in the MacroButton field. Clicking the object triggers the Ribbon utility for working with graphics - the field code no longer "hides" the graphic. There are a number of ways you can work around this:
Use an IncludePicture field (which works with the old graphics format) to bring in an outside picture file. Once the linked picture is in the field it can be converted to a static picture by selecting the IncludePicture field and pressing Ctrl+Shift+F9. Word respects the old graphic format and the picture is click-able.
{ MacroButton NameOfMacro {IncludePicture "C:\\Path\\picture.jpg" } }
Use the old *.doc file format. Note that this will restrict some of the things that can be done with the document, but it will force use of the old graphics engine.
Instead of a MacroButton field, use the WindowBeforeDoubleClick event or WindowSelectionChange event to run the code.
*With the exception of unlinking the IncludePicture field (which I discovered myself), this information came from this discussion on the Microsoft Answers site
If you want to run the macro with a single rather than a double-click (the default) you need to run the following line of code. This applies to the entire Word application and needs to be run everytime Word restarts. You could put it in an AutoNew macro in the template / AutoOpen macro in the document:
Application.Options.ButtonFieldClicks = 1
The simplest way to store the entire content you want to insert repeatedly is as a Building Block (formerly known as AutoText).
BuildingBlocks are stored in templates. If your document is being created from a template, that would be the logical place. Another possibility would be a special template you use for this purpose. Normal.dotm can also be used but keep in mind this does sometimes get removed.
(Note: if you're using a template for the document that would also be the best place to store the macro attached to the macro button.)
Once this is set up, all your code needs to do is insert the BuidlingBlock at the end of the document.
I have a word file containing many paragraph. I have a heading for each paragraph.Also listed all heading in a single page. What i want is, When user click on heading it can view only that paragraph only. he will not able to view other paragraph. To view other paragraph user need to comeback to the page where all headings are listed.
The way I would try to handle it is to put each paragraph into its own Continuous section and set all of the text as hidden. On the page where you have your headings, put a checkbox next to each one and in the checkbox properties, you can assign it to run a macro (remember to do this after you write your macros).
Now you just write a number of simple macros (one for each paragraph you have) that will change the font property of that paragraph by turning the hidden setting off, while changing the font properties of every other paragraph by turning the hidden settings on.
Now for your checkboxes, you'll need to set them up so that if one is selected, the rest of them are unselected. (You may be able to simply use a radio button instead of a checkbox, but I can't remember off the top of my head if radio buttons allow you to run a macro when selected.)
The thing you need to keep in mind is that some people may have their Word settings set up to always show hidden text, which would ruin the point of keeping stuff hidden. However, I believe you may get around that by adding another macro that turns that setting off as soon as the document is opened.
We have following requirement to be done via excel and VBA programming. Please check and let me know if it feasible to do so and if not what way would be best to do it.
There would be excel spreadsheet say excel 2007/2010 with 2 tabs.
1st tab contains normal excel data
In 2nd tab user can enter a particular value and then click on a button in same tab. Is it possibly to have a button in excel tab and can it raise events like windows/web applications?
Now if button can be kept in excel and it can raise button click event then on such an event we need to create xml files. Is it possible to create xml files adhering to schema using excel &/or VBA programming
You need to activate the developer tab (from backstage go to Options and check the visibility of this tab) to get access to normal windows controls, like buttons and drop-down lists etc. You can easily place those in Excel sheets and write event handlers: the controls support the full range of events, including OnClick, OnMouseEnter etc...
You can write custom text files directly from VBA, but you can't validate those. The usual way to do so is just to concatenate small XML blocks into a bigger file, so XML output is more like a normal text output. But it works fine and as long as you do not need to perform something really complicated it is also ok.
EDIT: You can easily add references to custom COM objects (.dll or .ocx) and use them directly in your VBA code. One very helpful suggestion (see the comment below) is to use the MS XML library.
To add a reference just open the code editor (Alt + F11) and then go to Options -> References. Most of the references you need will be already in the list and you just have to check them, but you can also add your own custom libraries by clicking on Browse.
I made a notepad using vb 2008 and I am facing a problem who I'd make the Statusbar.
any idea will be great.
Note: I am using the Textbox to read and write text
Thank you
You need to add a StatusStrip control to your form.
To find it, open the Toolbox, expand the "Menus & Toolbars" section, and double-click on the one named "StatusStrip".
Double-clicking on the control in the Toolbox will automatically add it to your form, and dock it along the bottom, just like it is in Notepad.
Once the control is there, you can customize it by changing properties in the Properties window. If you want to add information to the status bar, you do that by adding sub-controls inside of it. Click the drop-down arrow next to the "new" icon, and you'll see a list of possible choices:
"StatusLabel" — displays static text
"ProgressBar" — displays a progress bar, indicating the progress of a background operation
"DropDownButton" — displays a drop-down button, to allow a choice of multiple options
"SplitButton" — displays a drop-down button that allows a choice of multiple options, but also invokes the default option by a single click on the button.