Can a CRichEditCtrl know when someone sets its text? - mfc

When typing into a CRichEditCtrl, EN_CHANGE messages are generated. However MSDN says:
Rich Edit: Supported in Microsoft Rich
Edit 1.0 and later. To receive
EN_CHANGE notifications, specify
ENM_CHANGE in the mask sent with the
EM_SETEVENTMASK message. For
information about the compatibility of
rich edit versions with the various
system versions, see About Rich Edit
Controls.
The EN_CHANGE notification is not sent
when the ES_MULTILINE style is used
and the text is sent through
WM_SETTEXT.
I have several dialogs using a multi-line rich edit control, actually my custom CMyRichEdit class. That class automatically performs analysis when the text changes, but in the important case where the dialog is initially populated, no notification is seen.
The point is to avoid having to change our code-base more than absolutely necessary - the new control is being dropped in to replace existing ones. Chasing down every instance where getDlgItem(IDC_EDIT)->SetWindowText is used, or where DDX_Text(pDX, IDC_EDIT, m_strEdit) automatically links a string contents with the control, would mean a lot of trawling through code and re-testing everything altered.
Is there an easy way? Can MyRichEdit catch its own WM_SETTEXT messages?

ON_MESSAGE(WM_SETTEXT, OnSetText)
// fires every time someone calls SetWindowText
LRESULT MyRichEditCtrl::OnSetText(WPARAM wParam, LPARAM lParam)
{
return CWnd::Default();
}

Related

How do I replace the default right click context menu in a file open dialog box with my own

I would like to create a custom File Open dialog where I can replace the default context menu options shown when the user right clicks one of the files in the list, with my own context menu.
Based on articles such as this one, and this one, I tried adding:
UINT CALLBACK OfnHookProc(HWND hDlg, UINT uMsg, UINT wParam, LONG lParam)
and then refer to it using
ofn.lpfnHook = OfnHookProc;
I guess the ideal solution will be a class derived from OPENFILENAME. Not sure how.
For the Explorer-style Open dialog box:
The default templates are not available for modification.
The hook procedure does not receive messages intended for the standard controls in the dialog box.
So there seems little possibility to replace the default context menu via editing or subclassing the open dialog itself.
From the user's perspective, the chief benefit of the common dialog
box is its consistent appearance and functionality from
application to application. Hiding original controls or otherwise
changing the intended functionality of the original controls is a less appropriate customization.
However, there is a workaround maybe help:
Add your context menu item to the default one as an addition. Like this:
Refer to "Creating Cascading Menus with the ExtendedSubCommandsKey Registry Entry" for more detailed information.
Note: Modifying registry will affect all application instead of only your own application. So make sure keep this modification in a mini, required scope. For example, if putting this change in HKEY_CURRENT_USER\Software\Classes is enough don't put it in HKEY_LOCAL_MACHINE\SOFTWARE\Classes.
As mentioned by #remy-lebeau, you can do that using window subclassing as listed below:
get hWnd of the File Open dialog
replace WndProc via SetWindowLong(hWnd, GWL_WNDPROC, ..)
after that you will be able to track mouse position and handle WM_RBUTTONDOWN
To get window handle, you can use FindWindowEx, EnumWindows or even SetWindowsHookEx. Don't forget to pass unhandled messages to the original window procedure.

Getting title bar double-clicks

I am working on a MFC C++ application. I was working on a dialog that has SystemMenu property set to FALSE, so it does not have the ability to maximize. I want to handle the double-click message on the title bar. How can I do that?
EDIT:
I hope this time it will be clear for everybody. I have a dialog that does not have system menu (and system buttons or icon). When the user double-clicks the titlebar of that dialog, I want the program to call function x();.
Technically, you would have to handle WM_NCLBUTTONDBLCLK and check if the double click occurred in the caption area of the window, possibly by sending it WM_NCHITTEST and testing that the return value is HTCAPTION.
(Update: As JohnCz rightfully points out, sending WM_NCHITTESTis not actually necessary, since WM_NCLBUTTONDBLCLK already carries its result in wParam.)
Then you would only have to send WM_SYSCOMMAND with SC_MAXIMIZE in wParam to the window to maximize it.
In practice, however, it will not achieve much if your dialog box is not ready to handle size changes and layout its controls accordingly. This feature did not come out of the box in MFC last time I checked.
I think there is some kind of confusion here:
Frédéric Hamidi
You are correct, handling WM_NCLBUTTONDBLCLK message is the right way to go, however it is no necessary to call HitTest, since WM_NCLBUTTONDBLCLK message delivers hit information that MFC framework translates in the WM_NCLBUTTONDBLCLK handler.
Victor,
What is exactly that you are trying to achieve by handling WM_NCLBUTTONDBLCLK message?
Maybe there is some other way to fulfill your requirement once you make it clear to us.
The fact that you do not have system menu, does not prevent your app from receiving non-client area messages.

How could I detect when my application is minimized?

I have a program with an option to enable minimizing to the taskbar's notification area. In order for this to work, I need a reliable way of detecting when the user has minimized the application.
How can I do that using the Windows API in a C++ application?
When the user minimizes the window (either using the box on the title bar, or by selecting the "Minimize" option from the system menu), your application will receive a WM_SYSCOMMAND message. The wParam parameter of that message will contain the value SC_MINIMIZE, which indicates the particular type of system command that is being requested. In this case, you don't care about the lParam.
So you need to set up a message map that listens for a WM_SYSCOMMAND message with the wParam set to SC_MINIMIZE. Upon receipt of such a message, you should execute your code to minimize your application to the taskbar notification area, and return 0 (indicating that you've processed the message).
I'm not sure what GUI framework you're using. The sample code could potentially look very different for different toolkits. Here's what you might use in a straight Win32 C application:
switch (message)
{
case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_MINIMIZE)
{
// shrink the application to the notification area
// ...
return 0;
}
break;
}
I think you are looking for WM_SIZE. When you get this, check the wParam to get the specifics. Here is the MSDN page.
WM_SIZE
You can check the area size returned from GetClientRect - if zero it's minimised, works for me but may not work in all cases.
That's what IsIconic is supposed to determine, but it doesn't work consistently for me. (Oh, for a consistent way to determine this...)
For completeness, there's also GetWindowPlacement. The window state is revealed in the showCmd member of the WINDOWPLACEMENT structure, and if the window is minimized it has a value of 2, or SW_SHOWMINIMIZED.

Recognizing unknown mouse buttons

So I've been writing a simple Windows program, and it really irks me how in some other programs, they can't recognize the full range of input. For example, in Starcraft 2, you can't bind the extra two mouse buttons on a five-button mouse. For keyboard input, I've been using the WPARAM of the WM_KEYDOWN message, so that if it's unrecognized, I can still recognize it later, even if not display it in a usable form. But for mouse buttons, I've come a cropper, because they have their own messages. So if in the future, I get a seven-button mouse, how can I recognize the sixth and seventh buttons without having to re-write my application?
I don't think there is a generic "WM_BUTTONDOWN" message available.
The best way to check that out is to use Spy++ on a window. You'll see that there is no generic message sent out. Plus the actual values of all the WM_xxBUTTONDOWN do not follow any pattern either.
What I would do is configure the app to be able to understand 6 new messages entered manually or configured somewhere, for WM_[Z]BUTTONDOWN, WM_[Z]BUTTONUP and WM_[Z]BUTTONDBLCLK, plus all the corresponding WM_NCxxx messages, because luckily (sort of...), all existing messages more or less share the same wParam + lParam pattern.

WinApi equivalent of .NET KeyPreview

In .Net there is a feature called KeyPreview. How can I do this in WinApi. Maybe I don't necessarily need this but my hWnd has WM_KEYDOWN, but it does not receive it when my Text Box has focus. How can I achieve this?
Thanks
*Using pure Win32API...
is there an alternative, how could I handle the Text Box's WM_KEYDOWN?
You can try subclassing the edit control. Either "instance subclassing", to trap messages for only one window, or "global subclassing" to trap messages for all windows of that class (in your application, not system-wide).
The example here (http://msdn.microsoft.com/en-us/library/ms997565.aspx) shows how to subclass an edit control and trap the WM_GETDLGCODE message -it wouldn't be that difficult to change it to WM_KEYDOWN.
You may have problems previewing the keys used for dialog commands, e.g. TAB or RETURN, as they may be trapped higher up the food chain. You may need to look at changing WM_GETDLGCODE as well.
If you use MFC you can look at PreTranslateMessage (I am not sure regarding to PreTranslateMessage, but you can easily to verify whether to enough to override the function).
You can set keyboard hook.
There is no such a possibility in WinAPI to catch the messages belonging to controls in window procedure of parent window (although some exceptions exist).
What .NET basically does is that it routes all messages of all controls including their parent window to a single window procedure. Then it's easy to catch all the messages in one place.
This is your way to go - to set window procedures of all the controls into single procedure and there to catch all the messages
As window procedure also receives hwnd parameter, it's then also easy to determine the control to which the message belongs.