I have a page with possibly several content-editable iframes (editors).
Now I would like to use my custom Firefox extension to do the following:
Setting the cursor to the end (or last HTML element) of the editor the cursor actually is in.
I found many solutions to get the cursor's position, but I need one to set it.
Any suggestions?
XPCOM likely includes such functionality as part of the testing rig. Mochitest at least is capable of this (again, probably though XPCOM).
On the other hand, when a user is on the system this a generally a gross violation of user interaction practices. Be sure you have a good justification for doing it. It may seem convenient but what if they're doing something else whilst using your addon? I usually have various apps open at once, Fx extensions are only part of that. I don't want it taking control of my mouse, EVER.
Is there something wrong with setting the focus? At least that only forces the user's hand at a window level.
It also suspect it make it quite difficult to get past AMO review. You'd have to justify why it was necessary to invoke such low-level functionality. If you interact with a window, for example, the window might be able to affect the input of your functions which in turn control the mouse... and then a random web site has access to the user's window!
Found the solution to my problem myself. This code myself will set the Cursor position to the last Paragraph of my editor:
var frame = window.content.document.getElementsByTagName('iframe')[2];
var win = frame.contentWindow;
var editingSession = Components.classes["#mozilla.org/editor/editingsession;1"].createInstance(Components.interfaces.nsIEditingSession);
var editor = editingSession.getEditorForWindow(win);
selection = window.getSelection();
var body = frame.contentDocument.body;
text = frame.contentDocument.createTextNode(".");
body.lastChild.appendChild(text); // add textnode to be selected
var range = editor.document.createRange();
range.setStartBefore(text);
range.setEndAfter(text);
editor.selection.removeAllRanges();
editor.selection.addRange(range);
body.lastChild.removeChild(text); // remove Child
Related
I'm working on a concept that works like copy & paste but uses my own algorithm instead of using the clipboard.
We have users that use many different programs that contain part numbers. This is how my concept would work.
User highlights part number from any application (word, excel, pdf, JDE, etc)
Either by hotkey or clicking on another application the user launches my routine.
My routine grabs that text from the original application and processes it accordingly.
I know how to use the clipboard to get text.
What I'm not sure of is how to get currently selected text from the application that was active prior to running my code? Do I need to force my user to copy to clipboard first and then run my app or can I create my own copy/paste type windows add-in?
Preferred VB for this but can also use C++ or C# if easier.
As to the question why, because we want to the action to be seamless to the user. There will be several behind the scenes actions that take place and then the user will be presented a browser with pertinent information related to that part number. Ultimately, I don't want an in-between screen to pop up, but rather completely hidden from the user. If I require them to copy and then run my routine then I'm adding in one extra step to the user path that I'm hoping to avoid.
I looked into right click menu context a bit but found that each program can have their own override. I wasn't able to locate a way to globally override all right click context menus to include a new action.
From this article:
var element = AutomationElement.FocusedElement;
if (element != null)
{
object pattern;
if (element.TryGetCurrentPattern(TextPattern.Pattern, out pattern))
{
var tp = (TextPattern) pattern;
var sb = new StringBuilder();
foreach (var r in tp.GetSelection())
{
sb.AppendLine(r.GetText(-1));
}
var selectedText = sb.ToString();
}
}
It's in C# but it should be pretty trivial to translate.
I have an app, where I generate text (about 500 characters), and I would like the user to have some means of copying that text for use outside of the application.
I don't want to use any capabilities for this app (like web, or contacts).
Here's what I've tried (and why it's failed)
TextBox. IsReadOnly = true; SelectAll();
Can't SelectAll a read only text box
Turn off read only, hide the SIP
Can't hide the SIP on a (non-read-only) TextBox that the user is interacting with (I want to enable the user to copy, so needs to interact with the control)
allow edits, show sip, SelectAll()
The "copy" icon doesn't appear unless the user chose to select text
On selection changed (actually changed), SelectAll()
The "copy" icon doesn't appear unless the user selected the text? The copy icon appears erratically, nothing I would call an acceptable user experience.
So at this point, I'm quite far from what I want in a user experience, and I still don't have anything that works. Any suggestions?
Some other possible ways to answer my question include:
"How do I force the copy button to appear above text I programatically selected?"
"How do I change the selection behavior of a tap in a text box?"
Afaik there are some limitations to the Windows Phone 7 Clipboard:
Works only in TextBox and can only copy text upon users wish
Text is only kept until device gets locked. If your device gets locked, the clipboard will be wiped clean
Even if you try Clipboard.SetText Method, you will notice the SecurityException if you call this method without the users interaction. This is to keep the users data under control so that no rogue app can copy unrecognized Text.
But you could try Matt Laceys WP7Clipboard. It saves the clipboard content inside an image and can even copy bitmaps.
Try restyling the textbox as per http://mobileworld.appamundi.com/blogs/peterfoot/archive/2011/02/08/copyable-textblock-for-windows-phone.aspx
Here's what I eventually got mostly working
private void Export(StackPanel stacker)
{
var exportHeader = new TextBlock();
exportHeader.Text = "Export";
stacker.Children.Add(exportHeader);
var exportBox = new TextBox();
stacker.Children.Add(exportBox);
//exportBox.IsReadOnly = true; // hides SIP, but causes an exception with SelectAll() (pre-Mango, I haven't tried on Mango yet)
exportBox.FontSize = 1;
exportBox.Text = textToExport;
exportBox.GotFocus += new System.Windows.RoutedEventHandler((send, ev) =>
{
((TextBox)send).SelectAll();
});
exportBox.Focus();
}
Apparently, making the font size 1 makes the difference here, maybe because all of the text can appear on the screen at once? Who knows.
I accepted this answer, because no one else posted a better solution. I would appreciate a better solution. If you can get the SIP to go away, that would be awesome.
I need to create a SDI form with a formview that has two tabs, which encapsulate multiple dialogs as the tab content. But the form has to have a colored background.
And things like these makes me hate programming.
First, I tried CTabControl, via resource editor, tried different things, but the undocumented behavior and the quirks with no answers led me into a roadblock.
After many hours of searching, I found that there is a control called property sheet, which is actually what I need.
Some more searching later, I found that property sheet can even be actually embedded onto CFormView like so: http://www.codeguru.com/Cpp/controls/propertysheet/article.php/c591
And that the dialog classes derived from CPropertyPage can be directly added as pages via AddPage method of CPropertySheet.
Great! Not quite so... Some of the controls didn't worked, and were not created, ran into weird asserts. Turns out the DS_CONTROL style was missing from the dialogs. Found it completely accidentaly on Link, no word about that on MSDN!!!! Property page must have: DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_TABSTOP, and can have: DS_SHELLFONT | DS_LOCALEDIT | WS_CLIPCHILDREN styles! Not any other, which are created by default with resource editor. Sweet, super hidden information for software developers!
The quote in comments on that page: "OMG. That's where that behavior came from...
It turns out that the PlaySound API relied on that behavior when playing sounds on 64bit machines." by Larry Osterman, who as I understand works for Microsoft for 20 years, got me laughing out loud.
Anyway, fixed that, the dialog-controls(CPropertyPages) are created as expected now, and that part looks something remotely promising, but the next part with color is dead end again!
Normally you override WM_CTLCOLOR, check for control ID or hwnd and supply the necessary brush to set the color you need. Not quite so with CPropertySheet, the whole top row stays gray! For CTabCtrl it somehow works, for CPropertySheet it doesn't.
Why? Seems that the CPropertySheet is kinda embedded inside CTabControl or something, because if I override WM_ERASEBKGND, only the internal part changes the color.
Now it seems that there is a GetTabControl() method in the CPropertySheet, that returns the actual CTabCtrl* of the CPropertySheet. But since it's constructed internally, I can't find how to override it's WM_CTLCOLOR message processing.
There seems to be a way to subclass the windowproc, but after multiple tries I can't find any good source on how to do it. SubclassWindow doc on MSDN says: "The window must not already be attached to an MFC object when this function is called."?! What's that?
I tried creating a custom CCustomTabCtrl class based on CTabCtrl via MFC wizard, created an instance of it, called SubclassWindow from one of the CCustomPropertySheet handlers to override the internal CTabCtrl, but nothing works, mystical crashes deep inside MFC.
Tried setting WindowLong with GCL_HBRBACKGROUND for the internal CTabCtrl, nothing changed.
And worst of all, I can't find any sort of useful documentation or tutorials on the topic.
Most I can find is how to ownerdraw the tab control, but this is seriously wrong on so many ways, I want a standard control behavior minus background color, I don't want to support different color schemes, windows versions, IAccesible interfaces and all this stuff, and none of the ownerdraw samples I've seen can get even 10% of all the standard control behavior right. I have no illusion that I will create something better, I wont with the resources at hand.
I stumbled upon this thread, and I can't agree with the author more: http://arstechnica.com/civis/viewtopic.php?f=20&t=169886&sid=aad002424e80121e514548d428cf09c6 owner draw controls are undocumented PITA, that are impossible to do right, and there is NULL information on MSDN to help.
So is there anything I have missed or haven't tried yet? How to change the top strip background color of the CPropertySheet? Anyone?
Your only option is to ownerdraw the tab control. It's not that hard. Well, it is frustrating because MFC doesn't tell you how to make the necessary Win32 calls.
In your CPropertySheet-derived class, overwrite OnInitDialog() and add:
GetTabControl()->ModifyStyle(0,TCS_OWNERDRAWFIXED);
This puts your CPropertySheet-derived class in charge of drawing the tab control. Add a handler for WM_DRAWITEM (OnDrawItem) and change backgroundColor and textColor to match whatever colors you wanted. Code for OnDrawItem follows:
void CPropSht::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (ODT_TAB != lpDrawItemStruct->CtlType)
{
CPropertySheet::OnDrawItem(nIDCtl, lpDrawItemStruct);
return;
}
// prepare to draw the tab control
COLORREF backgroundColor = RGB(0,255,0);
COLORREF textColor = RGB(0,0,255);
CTabCtrl *c_Tab = GetTabControl();
// Get the current tab item text.
TCHAR buffer[256] = {0};
TC_ITEM tcItem;
tcItem.pszText = buffer;
tcItem.cchTextMax = 256;
tcItem.mask = TCIF_TEXT;
if (!c_Tab->GetItem(c_Tab->GetCurSel(), &tcItem )) return;
// draw it
CDC aDC;
aDC.Attach(lpDrawItemStruct->hDC);
int nSavedDC = aDC.SaveDC();
CBrush newBrush;
newBrush.CreateSolidBrush(backgroundColor);
aDC.SelectObject(&newBrush);
aDC.FillRect(&lpDrawItemStruct->rcItem, &newBrush);
aDC.SetBkMode(TRANSPARENT);
aDC.SetTextColor(textColor);
aDC.DrawText(tcItem.pszText, &lpDrawItemStruct->rcItem, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
aDC.RestoreDC(nSavedDC);
aDC.Detach();
}
Thank you for this solution but...
The above solution works well with one tab, but when you have multiple tabs it seems rename the wrong tabs. I needed to change the if statement for GetItem to:
if (!c_Tab->GetItem(lpDrawItemStruct->itemID, &tcItem )) return;
Needed lpDrawItemStruct->itemID to get the tabs named correctly
I want to persist the user's location in the document he or she is browsing, then bring them back to that spot when they return from tombstoning or between sessions.
My first approach was to wrap the browser component in a scrollviewer, but it turns out it handles its own scrolling and the scrollviewer never changes its verticaloffset.
My guess is that the browser component must have a scrollviewer or something like it embedded in it. I need to get the verticaloffset and scroll to an offset.
Any guesses how to get there?
My next approach would be a painful mish-mash of javascript and c# to figure out where they are...
Because of the way the WebBrowser control is built you'll need to track scrolling in Javascript then pass the location to managed code to handle storage of that value.
On resuming you'll need to have the managed code pass the scroll position to a Javascript function to reset the scroll position.
That's the theory but I haven't looked at the funcitonality around javascript scrolling events in the WebBrowser yet. That's the only place I can see possible problems.
Would be good to hear how you get on.
I've accepted Matt's answer, but I want to put in some details here. I'm also going to blog about how I did it once I'm completely done.
Since the WebBrowser component is essentially a black-box, you don't have as much control as I would like. Having said that, it is possible to get and set the vertical offset.
Javascript lets you ask for the value, but different browsers use different variations on HOW to ask. For THIS case I only have one browser to worry about.
First I make a couple of simple javascript functions:
function getVerticalOffset() {
return document.body.scrollTop;
}
function setVerticalOffset(offset) {
document.body.scrollTop = offset;
}
Next I call into the WebBrowser using the InvokeScript method on the browser object.
I'll post an update here with a link to my blog when I get the full write-up done.
I have been writing an eBook reader and had a similar question. Code for setting a scroll position has been easy enough to find.
Code for setting vertical scroll position:
string script = string.Format("window.scrollBy(0,{0});", "put your numeric value here");
wb_view.InvokeScript("eval", script);
Google didn't help much in finding solution for getting the value of current scroll position. Lacking any knowledge in javascript it took me almost two hours to get it right.
Code for getting the vertical scroll position:
var vScroll = wb_view.InvokeScript("eval",
"var vscroll = window.pageYOffset; vscroll.toString();");
Is there a way to change the colors used by plain Win32 menus (background, text, and highlight) for a single process, without using SetSysColors?
(SetSysColors does a global change, which is bad, and if you crash or forget to set the colors back with SetSysColors again before exiting, they will not be restored until you logout.)
The SetMenuInfo() API is your friend. It lets you apply any brush to paint your menu's background.
Something along these lines should solve your problem:
MENUINFO mi = { 0 };
mi.cbSize = sizeof(mi);
mi.fMask = MIM_BACKGROUND|MIM_APPLYTOSUBMENUS;
mi.hbrBack = hBrush;
HMENU hMenu = ::GetMenu(hWnd);
SetMenuInfo(hMenu, &mi);
If I believe your comment to Rob, it is for a skinned application, with special look and feel. So the way to go is probably indeed, as ferek points out (in an unfriendly way...) to use owner-drawn menus: you will be able to define precisely their look.
I have to ask, why? Adopting the regular Windows look-and-feel is good; it means users can be confident that there are consistent elements in your user interface, onto which they can map their experience using other software for the platform.
[I'm probably preaching to the converted, of course, but I thought I'd make the point so anyone who reads an answer for this doesn't start making all their menus sky-blue-pink 'cause it looks pretty.]