How do you prevent the user from changing anything other than the text in a Win32 Rich Edit control?
(i.e. They shouldn't be able to change the formatting of any text, add graphics, etc.; if they copy-paste new text, only the text should be kept, and associated formatting should be discarded.)
I've never found a particularly elegant way to handle this: what I've done in the past is:
1) Catch WM_KEYDOWN messages for the control and discard all formatting keys (Ctrl+E,J,R,L,1,2,5,+, and Ctrl+Shift+A,7)
2) Catch all paste operations by catching WM_COMMAND messages with an id of ID_EDIT_PASTE, and replace the paste message with a message EM_PASTESPECIAL,CF_UNICODETEXT to the control. (This is with MFC: Depending on what framework or language you're using, this may require catching Ctrl+V and similar rather than ID_EDIT_PASTE.)
Not pretty, I conceed, but it seems to work.
This answer is probably a bit late but for anybody else looking for an answer to this questions, the best way that I've found have total control of paste operations in a Rich edit control is to provide an implementation of IRichEditOleCallback::QueryAcceptData and then return S_FALSE to stop them all together or to filter out certain clip board formats by changing the lpcfFormat parameter.
The CRichEditView::QueryAcceptData function in MFC provides an excellent example of how this can be done. This will work for all kinds of paste operations including drag and drop so is the best way to get full control of what happens.
Even later :)
SendMessage(wndEdit, EM_SETEDITSTYLE, SES_EMULATESYSEDIT, SES_EMULATESYSEDIT)
seems to do the trick: paste pastes plain text, and the formatting hot keys are disabled.
SES_EMULATESYSEDIT: When this bit is on, rich edit attempts to emulate the system edit control (default: 0).
You still retain some of the "bonus" features of the richedit, such as scrollbars on demand.
Note: While this will prevent the pasting of richly formatted text into the RichEdit control, it will also prevent you from programatically formatting the text; all rich formatting is disabled.
Related
I know that styles have an attribute to allow/avoid changes in the text in which they are applied:
SCI_STYLESETCHANGEABLE(int style, bool changeable)
However, the documentation says "This is an experimental and incompletely implemented style attribute.", which seems it is not "production-ready"
I think there is another alternative, using "Indicators":
To protect a range of text, we could apply an specific indicator to it and in keydown event detect "del" & "backspace". If the character that follows current position (caret position) in "del" case or that precedes current position in "backspace" case has this indicator, then we must cancel the event and do not erase the text.
Which of this 2 alternatives is better? There is another better way?
Note: ScintillaNet is based on Scintilla and I assume that the extensive documentation of the last one is valid for both.
I share with you one of the responses in "scintilla-interest" google-groups that published Neil Hodgson, the creator of Scintilla.
[Ian G.]> SCI_STYLESETCHANGEABLE is what I tried initially before I resorted to writing this patch. The only real disadvantage I can see is that in cases like my own it doubles the number of styles needed because every visual style that can occur in a writeable region can also occur in a protected region, but I could live with that.
[Neil Hodgson] It would be better to use an indicator for protected areas since they are relatively space efficient and avoid doubling the number of styles.
complete post in scintilla-interest
I am trying to debug a tricky situation with auto-correction not getting correctly handled in a TextBox, but I am stuck:
I cannot find how the tapping of an auto-correction suggestion in the SIP gets communicated to the TextBox.
I have traced the KeyUp, KeyDown, TextInput, TextInputStart and TextInputUpdate events, but they do not seem to be involved in the update of the Text in the TextBox object.
Background:
When a language other than Greek is used, auto-correction works as it should for a TextBox in my app. However, when the language is set to Greek, nothing happens when tapping on the suggested word ... On the other hand, in TextBoxes in standard phone apps (e.g. adding text in the Notes section of a contact) Greek auto-correction works perfectly. So, my first guess is that there is something wrong with the TextBox rather than with the SIP. My plan is to subclass TextBox, modifying only its auto-correction handling parts.
Any help would be much appreciated,
Gerasimos
Update:
I made a few tests and this seems to be a problem in all non standard apps. Specifically, I tested the eBay and SkyMap applications and in both cases English auto-corrections work, while Greek do not.
The problem is easy to reproduce:
put a textbox in an application (with an inputScope that has auto-corrections enabled)
use a Greek keyboard layout
tap 1-2 random letters.
tap on one of the proposed auto-corrections. Only the final space is introduced, and in cases that the cursor is between two spaces (as I preferred to test it) nothing happens.
So, I believe that there is a bug somewhere in the framework part and not in the application code. Now, if we could find how this auto-correction tapping is communicated to the TextBox... :-)
You should not be able to interrupt the SIP directly, You can edit the content of the textbox after the value has been entered/changed. Alternatively, you can implement something like an autosuggest if your intentions are to change the content instead of the visuals.
This is easy in .NET (not my question) but I'm trying to figure out if it is possible to simply change the text of a string in a Win32 list box control given an index.
There is a GetText function that takes an item index but nothing to change the text of an existing item/string. My workaround will be to remove it and add it back in the box (which is also a weird prospect since there is no single command to add a string + item data -- these must be done carefully by inserting the string and then setting the item data on the index of the inserted string, which is tricky (not possible?) with sorting active).
Yes, the lack of a LB_SETITEMTEXT message is a bit weird.
You should put your Delete+Insert+SetData calls between calls to WM_SETREDRAW...
At the risk of being off topic...
I tend to use the ListView control all of the time. You'll want it in report view to mimic a listbox, and, as a plus, it supports multiple columns.
Oh.. and it has a LVM_SETITEM Message :)
http://msdn.microsoft.com/en-us/library/bb761186(v=VS.85).aspx
Although this question is old, but I think this documentation presented by Microsoft will be able to answer anyone questions based on this one.
So according to Microsoft documentation which you can find here
Changes the text of a list-view item or subitem. You can use this
macro or send the LVM_SETITEMTEXT message explicitly.
void ListView_SetItemText(
hwndLV,
i,
iSubItem_,
pszText_
);
And it also presents other macros for managing the list box. You can build a wrapper around this macros to simplify handling list view controls, etc.
I would like to know what should I do with GUI layout under WinAPI/MFC.
In the ideal world I should just create the form/dialog via resource editor, and everything should just work. In the real world the dialog editor is ancient behemoth from the ice-age and doesn't support most of the comctl32 controls.
This is where the problem creeps up. Dialog editor uses DLU units, and when I create new controls at runtime, I have to express them in pixel offsets.
I stumbled upon one article about calculating DLUs based on font http://support.microsoft.com/kb/145994/en-us, but also saw a warning somewhere that dialogs can have non system fonts in some circumstances, so this approach is not very safe. Plus the article seems to look only at English characters, without regard to all other characters in unicode space which might be wider?.
Has anyone done a research in this direction and found a better way?
P.S.: No Winforms/WPF/Delphi, requirements.
the dialog editor is ancient behemoth from the ice-age and doesn't support most of the comctl32 controls
It doesn't need to support the controls directly, you can still use it just for positioning by inserting it as a custom control and filling in the window class in the property page. For example, that's how I insert link controls in VS2005: as a custom control with class "SysLink".
MapDialogRect (mentioned in the article) is the function that Windows uses to translate the dialog units in the dialog resource to pixel units. MapDialogRect works (where GetDlgBaseUnits fails) because its given an actual handle to the dialog box, and can send it a WM_GETFONT message to retrieve the actual font the dialog will be rendered with.
I have a Listbox where all cells are editable.
While the user is typing text in the ActiveCell (Textfield) she may decide to paste text.
I would like to examine the paste-text and perform different paste operations depending on whether it is multiline or not.
Is there any way to create an EditPaste MenuHandler specifically for ListBox1.ActiveCell?
You should be able to use the keyboard async command and intercept the paste command in the Listbox.CellKeyDown event. Then take a look at the clipboard object to see what text it has in it.
Kind of a kludge, but I can't think of any other way to do it since the ActiveCell handles cut/copy/paste on its own without intervention.