i discovered today that Windows 7 comes with a very impressive MathPanel utility, for performing handwriting recognition of equations:
Which is fine. (Here i've entered the formula for the part of the sRGB color space gamma conversion)
But now i don't seem to be able to do anything with it.
There is an Insert button. i would assume that clicking Insert would insert it into the application that is active behind it (much like the On-Screen Keyboard works):
Except i assume it would operate as a Paste operation.
i can find no information in the help on what is required by an application to make it work. There is no mention of any special API some software must support.
Nor can i find any information on MSDN about what special API is required to accept the insertion of an equation.
What API, registration, callback, listener, message, COM Object do i have to implement so that i will receive MathPanel input?
The only reason i mention MathML is because an answer on SuperUser mentioned MathML:
Theoretically, any app that supports MathML (Mathematical Markup Language) can be used with the Windows 7 Math Input Panel. The Math Input Panel only works with programs that support MathML. Here are a few such apps: StarOffice, OpenOffice, Opera and Maple.
Well how do i make my program support MathML?
As far as i know MathML is a markup language; not a Windows API. It would be like saying, "How do i make my program support HTML?" Html is text, and you can paste it anywhere.
MathPad refuses to paste unless i "support" MathML?
Update
Inspecting the IDataObject on the clipboard after clicking Insert, i see two formats available (neither of which are text, which explains why i do not get any markup):
Format 1:
CLIPFORMAT cfFormat: "MathML Presentation" (49839)
PDVTargetDevice ptd: 0x00000000
DWORD dwAspect: DVASPECT_CONTENT
DWORD lindex: -1
DWORD tymed: 1 (TYMED_HGLOBAL)
Format 2:
CLIPFORMAT cfFormat:"MathML" (49838)
PDVTargetDevice ptd: 0x00000000
DWORD dwAspect: DVASPECT_CONTENT
DWORD lindex: -1
DWORD tymed: 1 (TYMED_HGLOBAL)
So at least now i have some clipboard formats:
"MathML Presentation"
"MathML"
i still cannot find anything on MSDN about either clipboard format.
Spying on messages sent to my window, looks like the Math Input Panel application sends a Ctrl+V:
WM_KEYDOWN (0x11) VK_CONTROL
WM_KEYDOWN (0x56) V key
WM_CHAR (0x16)
WM_KEYUP (0x11) VK_CONTROL
WM_KEYUP (0x56) V key
So you need to recognize that someone's trying to hit Ctrl+V. Then you must extract the contents.
First register the three clipboard formats:
Handle CF_MathML_Presentation = RegisterClipboardFormat("MathML Presentation");
Handle CF_MathML_Content = RegisterClipboardFormat("MathML Content");
Handle CF_MathML = RegisterClipboardFormat("MathML");
Note: Appendix B of the W3C's Mathematical Markup Language (MathML) Version 3.0 documents the Windows clipboard format names to be registered:
Generic MathML Windows Clipboard Name: MathML
Presentation MathML Windows Clipboard Name: MathML Presentation
Content MathML Windows Clipboard Name: MathML Content
Then get a handle on the IDataObject in the clipboard:
IDataObject dataObject;
OleGetClipboard(dataObject);
Then enumerate all the formats, looking for the one you like:
IEnumFORMATETC enum;
dataObject.EnumFormatEtc(DATADIR_GET, out enum);
String mathXml = "";
foreach (FormatEtc format in enum)
{
if (format.cfFormat = CF_MathML_Presentation) ||
(format.cfFormat = CF_MathML_Content) ||
(format.cfFormat = CF_MathML)
{
//We know how to handle these formats:
STGMEDIUM medium;
dataObject.GetData(format.cfFormat, out medium);
mathXml = GetStringFromStorageMedium(medium); //handles all the nasty HGlobal/IStream/IStorage nonsense
}
}
ShowMessage(mathXml); //tada!
Microsoft also allows you to program the Math Input COM object:
//Create the COM object
IMathInputControl mathInputControl = CreateComObject(CLSID_MathInputControl);
mathInputControl.Show();
You can then create an object that receives the notification events:
class MathEvents : _IMathInputControlEvents
{
public HRESULT Insert(String mathXml)
{
//Notifies the event handler when the Insert button is clicked.
MessageBox.Show(mathXml);
return S_OK;
}
public HRESULT Clear()
{
//Notifies the event handler when the Clear button is clicked.
return S_OK;
}
public HRESULT Close()
{
//Notifies the event handler when the Close button is clicked.
return S_OK;
}
public HRESULT PaintHRESULT Paint(LONG_PTR hdc, LONG Left, LONG Top, LONG Right, LONG Bottom, LONG Element, LONG State)
{
//Notifies the event handler when the buttons and background of the control require painting.
return S_OK;
}
The missing ingredient is how to give mathInputControl a reference to our callback object.
That's super-secret complicated COM code, involving ConnectionPointContainer, andAdvise`, which cannot be done from C#.
But you don't need to, you can just use Ctrl+V.
I think it is officially called the "Math Input Panel" (MIP). The MathType product supports it and provides a menu item to run it. As other replies here mention, clicking MIP's Insert button sends a Ctrl-V to the window underneath it. If that window supports that keyboard shortcut and handles MathML, then it will work.
While the MathML Clipboard Format is the recommended way to handle MathML input on a paste, if you are implementing MathML support in your app you should also accept MathML text offered as CF_UNICODETEXT. Some apps support copying MathML to the clipboard but do not seem to know about the MathML Clipboard Format. Of course, your paste code will have to sniff the text to identify MathML as opposed to regular non-MathML text. You should also consider accepting a drag-and-drop as well as a paste.
The Math Input Control is a related but slightly different configuration of MIP. If I remember correctly, it lacks the history and some other features of the MIP. We started working with it for MathType and quickly realized that there's no advantage to it. You should just ignore it and just support paste and drag-and-drop of MathML. Add a Math Input Panel menu item if it makes sense for your app.
The clipboard format "MathML Presentation" actually contains text; I've tried this before using the Windows API GetClipboardData().
Moreover, if you copy a MathML fragment to the clipboard as plain text (e.g., CF_TEXT) and then paste it to a Word document, you will get plain text also, i.e., Word will NOT interpret it as Presentation MathML.
For Word to do so, you have to copy it as both CF_TEXT and as "MathML Presentation". To obtain the ID of the latter, try registering "MathML Presentation" as a clipboard format as suggested by Ian Boyd. Windows will return its clipboard format ID; use this ID with SetClipboardData().
Related
I have an old windows application with it's Ocxs. I want to localize it's OCX to arabic. no problem on changing labels and strings.
but I can't change layout to Right to left.
I find some resources about using Mirroring in windows. but the provided samples don't help me. Link1 & Link2
I'm not a VB fan and don't have enough experience.
Is there any clear and tested approach for VB to mirroring UI?
From Platform SDK 2001
Complex Scripts in Edit Controls
A complex script is a language whose printed form is not laid out in a simple way. For example, a complex script may allow bi-directional rendering, contextual shaping of glyphs, or combining characters. The standard edit controls have been extended to support multilingual text and complex scripts. This includes not only input and display, but also correct cursor movement over character clusters (in Thai and Devanagari script, for example).
A well-written application will receive this support automatically, without modification. Again, you should consider adding support for right-to-left reading order and right alignment. In this case, toggle the extended style flags of the edit control window to control these attributes, as shown in the following example:
// ID_EDITCONTROL is the control ID in the resource file.
HANDLE hWndEdit = GetDlgItem(hDlg, ID_EDITCONTROL);
LONG lAlign = GetWindowLong(hWndEdit, GWL_EXSTYLE) ;
// To toggle alignment
lAlign ^= WS_EX_RIGHT ;
// To toggle reading order
lAlign ^= WS_EX_RTLREADING ;
After setting the lAlign value, enable the new display by setting the extended style of the edit control window as follows:
// This assumes your edit control is in a dialog box. If not,
// get the edit control handle from another source.
SetWindowLong(hWndEdit, GWL_EXSTYLE, lAlign);
InvalidateRect(hWndEdit, NULL, FALSE);
Windows 2000/XP: The standard edit control supports a context menu that allows the user to toggle the reading order and insert/display Unicode bi-directional control characters.
I want to implement a text editor from scratch which supports IAccessible interface. I am using MFC and Win32 API.
When the caret position change in the standard text editors like Notepad, the corresponding letter, word or line to the caret movement is pronounced by client tools like Narrator, JAWS or etc. I don't know how to implement this feature. I search the internet and read the MSDN documentation.
I read in http://msdn.microsoft.com/en-us/library/dd317978.aspx and http://msdn.microsoft.com/en-us/library/dd373892.aspx that client asks for caret by AccessibleObjectFromWindow method from OS, and OS send WM_GETOBJECT to the application. WM_GETOBJECT messages received in the corresponding window callback function, but hWnd for caret movement event is NULL. I checked the thread message queue, but WM_GETOBJECT didn't receive at all in the thread message queue.
One method that has worked somewhat, but not the correct solution is to call
NotifyWinEvent( EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CLIENT, CHILDID_SELF )
when the caret move by user. And when client ask for the changed name, I return the corresponding text related to the caret movement.
HRESULT CMyEditor::get_accName(VARIANT varChild, BSTR *pszName)
{
*pszName = SysAllocString( L"CORESPONDING TEXT TO THE CARET MOVEMENT" );
return S_OK;
}
The client would use the SetWinEventHook() function to track the following events of the caret :
EVENT_OBJECT_CREATE
EVENT_OBJECT_DESTROY
EVENT_OBJECT_SHOW
EVENT_OBJECT_HIDE
EVENT_OBJECT_LOCATIONCHANGE
EVENT_OBJECT_FOCUS
If you use a custom control, you need to use NotifyWinEvent() to fire those events yourself, especially EVENT_OBJECT_LOCATIONCHANGE which should trigger the narration.
When the client handle thoses events, it should access the IAccessible interface of the object he's tracking using AccessibleObjectFromEvent().
As you say, Microsoft Active Accessibility would handle this call and send an WM_GETOBJECT message to the corresponding window depending on the handler given to AccessibleObjectFromEvent() (which should be the handler contained in the event).
When you receive the WM_GETOBJECT for the caret you should return the corresponding IAccessible interface which would report the proper accRole and accLocation.
If you're not receiving the right WM_GETOBJECT message it may be because you're not triggering the right events.
You can use the Accessible Event Watcher to check if the right events are sent :
http://msdn.microsoft.com/en-us/library/windows/desktop/dd317979%28v=vs.85%29.aspx
See the Developer's Guide for Active Accessibility Servers on MSDN :
http://msdn.microsoft.com/en-us/library/windows/desktop/dd318053%28v=vs.85%29.aspx
Edit
Also, if you're using the standard caret provided by Riched20.dll (in a Rich Edit as instance), the documentation stipulate that unlike other UI elements, it does not have an associated window handle.
I want to make a custom message box. What I want to customize is the button's text.
MessageBoxW(
NULL,
L"Target folder already exists. Do you want to overwrite the folder?",
L"No title",
MB_YESNOCANCEL | MB_ICONQUESTION
);
I'd like to just change the buttons text to Overwrite, Skip, Cancel.
What's the most simple way?
I have to make this as having same look and feel with Windows default messagebox.
As said by others, a typical way is to create a dialog resource and have a completely independent dialog, which GUI you need to design in the way that it looks like standard dialog (to meet your request for feel and look). If you want to accept text messages, you might probably need to add code which resizes the window appropriately.
Still, there is another option for those who feel like diving into advanced things. While MessageBox API does not offer much for fint tuning, you still have SetWindowsHookEx in your hands. Having registgered the hook, you can intercept standard MessageBox window procedure and subclass it in the way you like.
Typical things include:
changing button text
adding more controls
adding timed automatic close
Hooking standard window can do all of those.
UPD. Hey, I realized I have some code with SetWindowsHookEx to share: http://alax.info/blog/127
You could create an own dialog. Or you could use a window hook as described in this article.
An archived version of the article can be found on web.archive.com.
Make a dialog resource (with a GUI editor, or by hand) and call DialogBox on it. There's no way to alter MessageBox behaviour, other than what's supported by its arguments.
That said, your message box can very well use stock Yes/No options.
The task dialog functionality introduced in Vista does exactly what you want and follows the prevailing system theme. However, if you have to support XP, then this will be of little comfort to you.
I know this question is old, but I just stumbled upon it now.
I would like to expand the other answers in regards to using a TaskDialog instead of a MessageBox. Here's a concise example of using a TaskDialog to do precisely what was asked; change the button's texts:
const TASKDIALOG_BUTTON buttons[] = { {IDYES, L"Overwrite"}, {IDNO, L"Skip"}, {IDCANCEL, L"Cancel"} };
TASKDIALOGCONFIG taskDialogConfig = {
.cbSize = sizeof(TASKDIALOGCONFIG),
.pszMainIcon = TD_WARNING_ICON, // TaskDialog does not support a question icon; see below
.pButtons = buttons,
.cButtons = ARRAYSIZE(buttons),
.pszWindowTitle = L"No title",
.pszContent = L"Target folder already exists. Do you want to overwrite the folder?"
};
TaskDialogIndirect(&taskDialogConfig, NULL, NULL, NULL);
Some noteworthy things:
You need to use TaskDialogIndirect, not the basic TaskDialog function
when not specifying a parent window, the icon specified in pszMainIcon is displayed in the title bar as well
There is no equivalent to the MessageBox's MB_ICONQUESTION, quoting a quote from this forumpost: Don't use the question mark icon to ask questions. Again, use the question mark icon only for Help entry points. There is no need to ask questions using the question mark icon anyway—it's sufficient to present a main instruction as a question.
checking which button was selected would have to be done by passing a pointer to an int as the second argument of TaskDialogIndirect and checking its value on return (the documentation should be pretty clear)
Here is a small open source library that allows you to customize Message Boxes. Developed by Hans Ditrich.
I have successfully used it in another POC that allows embedding a custom icon in such MessageBox that can be called even from a Console application.
I should also point to the Task Dialog. Here is an example of using it:
int nButtonPressed = 0;
TaskDialog(NULL, hInst,
MAKEINTRESOURCE(IDS_APPLICATION_TITLE),
MAKEINTRESOURCE(IDS_DOSOMETHING),
MAKEINTRESOURCE(IDS_SOMECONTENT),
TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON,
TD_WARNING_ICON,
&nButtonPressed);
if (IDOK == nButtonPressed)
{
// OK button pressed
}
else if (IDCANCEL == nButtonPressed)
{
// Cancel pressed
}
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.
I have a third-party GUI program that I'm wrapping with a Python class (using ctypes).
Are there Win32 API functions that can do the following?
1) Obtain the window handle for a window at a given screen location.
2) Obtain the window handle for a Button or Static window with a given caption.
3) Send text to an Edit window.
4) Extract text from a RICHEDIT instance.
I have WinSpy (a Spy++-type app) and know that it's possible to obtain window handles and captions using that tool, but I need something that works within Python.
I assume that Python's ctypes gives me access to any function within the Win32 API, so I've been scanning MSDN (especially this windows/messages section). I can't seem to find anything that works.
Thanks,
Mike
WindowFromPoint
FindWindowEx to find a child of a window with a given class and name (caption). Repeat operation to get through each parent-child indirection. EnumChildWindows can be helpful too.
SendMessageTimeout + WM_SETTEXT
SendMessageTimeout + WM_GETTEXT or EM_STREAMOUT
I had trouble finding a very simple example for WM_GETTEXT with pywin32 and figured here might be a good place to add one, since it answers part of the question:
MAX_LENGTH = 1024
handle = # A handle returned from FindWindowEx, for example
buffer = win32gui.PyMakeBuffer(MAX_LENGTH)
length = win32gui.SendMessage(handle, win32con.WM_GETTEXT, MAX_LENGTH, buffer)
result = buffer[:length]