Let my MFC dialog receive keystroke events before its controls (MFC/Win32 equivalent of WinForms "KeyPreview") - windows

I have an MFC dialog containing a dozen or so buttons, radio buttons and readonly edit controls.
I'd like to know when the user hits Ctrl+V in that dialog, regardless of which control has the focus.
If this were C#, I could set the KeyPreview proprety and my form would receive all the keystrokes before the individual controls - but how do I do that in my MFC dialog?

JTeagle is right. You should override PreTranslateMessage().
// Example
BOOL CDlgFoo::PreTranslateMessage( MSG* pMsg )
{
// Add your specialized code here and/or call the base class
if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN )
{
int idCtrl= this->GetFocus()->GetDlgCtrlID();
if ( idCtrl == IDC_MY_EDIT ) {
// do something <--------------------
return TRUE; // eat the message
}
}
return CDialog::PreTranslateMessage( pMsg );
}

Add a handler to override PreTranslateMessage() in the dialog class, and check the details of the MSG struct received there. Be sure to call the base class to get the right return value, unless you want to eat the keystroke to prevent it going further.

Related

How to create a action for UIReturnKeyType.Done in UITextView in xamarin iOS

I am trying to change the UITextView keyboard return button in to Done button.
I need to close the keyboard when I press the Done button.
I have create a UITextView and change the return button in to Done button.
This is my code
PhotoTitle = new UITextView
{
TranslatesAutoresizingMaskIntoConstraints = false, Editable = true, AccessibilityIdentifier = "PhotoTitle",
ReturnKeyType = UIReturnKeyType.Done
}
The keyboard showing Done button successfully. if I press it just behave like return button.
And I can not find a particuler event for fire when tap on Done button.
First of all you have to keep remember that, UITexiView is a scrollable UI widget. So, when you change the keyboard's default Return key in to Done button, you are hiding the opportunity of go to new line inside your UITextView. Therefore my suggestion is, if you are using a UITextView and you need a Done button by keeping the default keyboard, you should add a UIToolBar on top of the keyboard where you can place the Done button.
Since I'm not aware of your real need, which may do not need go to a new line and just need to exit the keyboard when user tap on the Return/Done button, here how you need to do it.
public override void ViewDidLoad()
{
base.ViewDidLoad();
TextView.WeakDelegate = this;
}
[Export("textView:shouldChangeTextInRange:replacementText:")]
public bool ShouldChangeText(UITextView textView, NSRange range, string text)
{
if (text.Equals("\n"))
{
TextView.ResignFirstResponder();
return false;
}
return true;
}
That is quite easy actually subscribe to the ShouldReturn event of the UITextField with a delegate or anonymous method that will call ResignFirstResponder on the field.
You can check this example project that shows how to do it
this.txtDefault.ShouldReturn += (textField) => {
textField.ResignFirstResponder();
return true;
};

How do I get notification from a `CEdit` box?

I have a CEdit box where a user can enter relevant information. As soon as he\she starts writing in the box, I need a notification so that I can call doSomething() to perform some other task. Does Windows provide a callback, and if so, how do I use it?
With MFC there's no callback as such, rather you do this by implementing a handler for the appropriate event. You need to handle one of two events: WM_CHAR or EN_CHANGE
Handle the dialog's EN_CHANGE for example duplicating in realtime the entered text elsewhere on the dialog. You need to firstly add an entry in the dialog's message map, and secondly override the appropriate handler:
BEGIN_MESSAGE_MAP(CstackmfcDlg, CDialog)
ON_EN_CHANGE(IDC_EDIT1, &CstackmfcDlg::OnEnChangeEdit1)
END_MESSAGE_MAP()
void CstackmfcDlg::OnEnChangeEdit1()
{
CString text;
m_edit.GetWindowText(text);
m_label.SetWindowText(text); // update a label control to match typed text
}
Or, handle the editbox class's WM_CHAR for example preventing input of certain characters, e.g. ignore anything other than a digit for numerical entry. Derive a class from CEdit, handle the WM_CHAR event of that class (not the dialog) and make your edit control an instance of that class.
BEGIN_MESSAGE_MAP(CCtrlEdit, CEdit)
ON_WM_CHAR()
END_MESSAGE_MAP()
void CCtrlEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// Do nothing if not numeric chars entered, otherwise pass to base CEdit class
if ((nChar >= '0' && nChar <= '9') || VK_BACK == nChar)
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
Note that you can use the VS IDE to put in stubs for the handler overrides by using the Properties bar with the mouse selection in the message map block.
EDIT: Added example code, and corrected explanation of WM_CHAR which I had wrong.
If you double click on the edit box in the resource editor it automatically creates the OnEnChanged event for you.
The following assumes that you have an MFC dialog application.
The class wizard can be started with a right-click:
Double-click the Control ID (has an icon with a small green plus) of the new edit control to add the corresponding member variable to the class.
The class and event wizards will update the class definition and add a CEdit member:
afx_msg void OnEnChangeEdit1(); // Added by event wizard
CEdit m_edit1; // member added by class wizard
The class wizard will update the function:
void CMFCApplication5Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_edit1); // new variable added with class wizard
}
Double-clicking the control or right-clicking and selecting the add event wizard will update the message map and create the function declaration and definition:
BEGIN_MESSAGE_MAP(CMFCApplication5Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_EN_CHANGE(IDC_EDIT1, &CMFCApplication5Dlg::OnEnChangeEdit1) // new event handler added with wizard
END_MESSAGE_MAP()
Finally the code may be updated to interact with the edit control:
void CMFCApplication5Dlg::OnEnChangeEdit1()
{
// TODO: Add your control notification handler code here
CString text;
m_edit1.GetWindowText(text);
//m_edit1.SetWindowText(text);
}

Control press "back button" and disable close the application using a dialog for confirm - wp7

I need show a simple dialog with the question : 'Do you want to exit the application?' YES or NO.
This dialog will be shown when the user presses the back button of the device.
I know how I can show this dialog , but I don't know how to disable the back action: close app.
It's always closed.
If I understand you correctly, you want to display a confirmation dialog when the user clicks the back button on the main page of your app to ask whether they really want to exit. If the user selects Yes the app exits, otherwise you cancel the back navigation. To do this, in the MainPage class constructor hook up an event handler
MainPage()
{
BackKeyPress += OnBackKeyPressed;
}
void OnBackKeyPressed( object sender, CancelEventArgs e )
{
var result = MessageBox.Show( "Do you want to exit?", "Attention!",
MessageBoxButton.OKCancel );
if( result == MessageBoxResult.OK ) {
// Do not cancel navigation
return;
}
e.Cancel = true;
}

Click lost on focusing form

Question:
Is there a way to always let a click, that brings a form in to focus, through an have effect on the form?
Background:
With my (C# win form) application out of focus I can hover the form and get shades and borders indicating where my mouse is.
Clicking for example a menu entry (File) the form gets focus but the file menu does not get click. This takes an additional click.
For an ordinary button on the form only one click is required.
This can be fixed by setting focus before the click occurs. Se code:
class ToolStripEx : System.Windows.Forms.ToolStrip
{
protected override void WndProc(ref Message m)
{
// WM_MOUSEACTIVATE = 0x21
if (m.Msg == 0x21 && this.CanFocus && !this.Focused)
{
this.Focus();
}
base.WndProc(ref m);
}
}
This approach also works on MenuStrip
I found a few helpful articles – especially this one by Rick Brewster. The solution lies in overriding the WndProc method for the ToolStrip (or MenuStrip):
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (this.clickThrough &&
m.Msg == NativeConstants.WM_MOUSEACTIVATE &&
m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT)
{
m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
}
}

Key Preview and Accept Button

Using winforms, I have set the KeyPreview property to true and have event handles for the proper key events within the base form as well.
Within the forms that inherit from it, I set the AcceptButton property based on the requirements of the application.
There are certain cases in which I want the enter key to have functionality different than that of the AcceptButton.
I was hoping to capture the enter key press within my base form and check for the special cases where I do not want the AcceptButton event to fire.
It appears though, that the AcceptButton click is fired before any of the key events within my basef form. I could write functionality into the click events of the possible acceptbuttons, but, in my opinion, that would be a hack.
Any suggestions?
Thanks.
Another way to handle this is to override the form's ProcessDialogKey() method where you can suppress the accept and/or cancel buttons. For example, I have an application with a filter editor that filters a grid based on user input. I want the user to be able to hit the return key when the filter editor control has the focus to apply the filter. The problem is the accept button code runs and closes the form. The code below resolves the issue.
protected override bool ProcessDialogKey(Keys keyData)
{
// Suppress the accept button when the filter editor has the focus.
// This doesn't work in the KeyDown or KeyPress events.
if (((keyData & Keys.Return) == Keys.Return) && (filterEditor.ContainsFocus))
return false;
return base.ProcessDialogKey(keyData);
}
You can take this even further by dropping the following code in a base dialog form. Then you can suppress the accept button for controls in subclasses as necessary.
private readonly List<Control> _disableAcceptButtonList = new List<Control>();
protected override bool ProcessDialogKey(Keys keyData)
{
if (((keyData & Keys.Return) == Keys.Return) && (_disableAcceptButtonList.Count > 0))
{
foreach (Control control in _disableAcceptButtonList)
if (control.ContainsFocus)
return false;
}
return base.ProcessDialogKey(keyData);
}
protected virtual void DisableAcceptButtonForControl(Control control)
{
if (!_disableAcceptButtonList.Contains(control))
_disableAcceptButtonList.Add(control);
}
As our workaround, we captured the enter and leave event for the control that we wanted to have override the acceptbutton functionality. Inside the enter event, we held the current accept button in a private variable and set the acceptbutton to null. On leave, we would reassign the acceptbutton back to the private variable we were holding.
The KeyPreview events could have done something similar to the above. If anyone has a more elegant solution, I would still love to know.
Thanks.

Resources