How to give accelerator key to keyboard backspace key - mfc

I am developing MFC dialog based application. my requirement is when user click on backspace it should be focused on Edit text control and delete text as normal backspace works.
this dialog has single edit box and multiple buttons, wherever currently focus on current dialog when user click on backspace, it should be focus on edit box and able to work as backspace key.

You can handle the key in an override of PreTranslateMessage(MSG* pMsg):
BOOL MyDialog::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN &&
pMsg->wParam == VK_BACK)
{
// do your thing here
if (GetFocus() != &theEditBox)
GotoDlgCtrl(&theEditBox);
}
return MyDialog::PreTranslateMessage(pMsg);
}

Related

MFC) Making TreeCtrl loses its item focus

I have used TVN_SELCHANGED message to find out what user select in item tree (Menu).
However, if user continually click same item, that message does not occur.
I want treeCtrl to lose its item selection for occurring TVN_SELCHANGED.
(In other words, I want to make event happened even if user click same item consecutively)
How do I do that?
TVN_SELCHANGE will not help. Nothing is changed, so the notification isn't sent. Even it makes no sense for me. What should a UI do, if a user clicks on an already selected item? Nothing... I would guess.
If you want to handle this, you have to do it by yourself.
You can use WM_LBUTTONDOWN or NM_CLICK, to track the click.
Than use TVM_HITTEST to check what was clicked by the user.
Now you can compare the current selection (TVM_GETNEXTITEM and check for TVGN_CARET)
compare old and new selection.
After all, pass the click to the default handler.
The only time the TreeCtrl will get notified when an item is selected is: TVN_SELCHANGE. In case of same selection, this won't help. But there is another way to get notified.
Add PreTranslateMessage command in your dialog class where TreeCtrl is used and add the code written below.
//---------------------------------------------------------------------------
BOOL MyDlgClass::PreTranslateMessage(MSG* pMsg)
{
UINT msgValue = pMsg->message;
//here I have compared L button down event, you can use any
//mouse/keyboard event that you want to compare.
if (msgValue == WM_LBUTTONDOWN)
{
CPoint point;
point.x = (int)(short)LOWORD(pMsg->lParam);
point.y = (int)(short)HIWORD(pMsg->lParam);
OnLButtonDown(pMsg->message, point);
}
}
void MyDlgClass::OnLButtonDown(UINT nType, CPoint point)
{
UINT uFlags;
HTREEITEM hItem = m_treeCtrl.HitTest(point, &uFlags);
if ((hItem != NULL) && (TVHT_ONITEMBUTTON & uFlags))
{
return;
}
//TVHT_ONITEMBUTTON detects if user has clicked + or - button of tree
//view.
//Add code to perform your operations on hItem.
}

How to avoid mouse click on one widget triggering the signals in others in Qt?

In my app I'm using a QTableView to show a list of images and I select some of the images by clicking left mouse button and pressing control keyboard button when I do so the app looks as the below stated image:
But then when I try to use other buttons on the app like "Destination" and then try to select a destination folder then the app looks like this below:
Problem occurs when I click the "select folder" button and try to select the folder. What happens is that click on the folder selection tab, triggers QTableView widget in which I show the image and the deselects all the selected images. I want to avoid it. The way I now track the left mouse button clicks on QTableView widget is as below:
bool MainWindow::eventFilter(QObject* obj, QEvent *ev)
{
if(obj == ui->listOfImages->viewport())
{
QMouseEvent * mouseEv = static_cast<QMouseEvent*>(ev);
if((mouseEv->buttons() & Qt::LeftButton) && (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier) == true))
{
controlButtonCounter++;
fetch = true;
return QObject::eventFilter(obj,ev);
}
else if((mouseEv->buttons() & Qt::LeftButton) && (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier) == false))
{
if(selectedImages.size()>0)
{
ui->listOfImages->clearSelection();
selectedImages.clear();
}
fetch = false;
controlButtonCounter = 0;
}
}
return QObject::eventFilter(obj,ev);
}
Here ui->listOfImages is the QTableView widget. Other things like controlButtonCounter are irrelevant in taking the mouse clicks, I use it for other purposes.
Please say me how I can avoid triggering QTableView widget when I'm pressing on other things that fall in the same region as the QTableView.
if(obj = ui->listOfImages->viewport())
You are not doing a comparison there, you are assigning a value to the obj variable.
It should be like this:
if(obj == ui->listOfImages->viewport())
I'm not sure but maybe it can help you:
void setWindowModality(Qt::WindowModality windowModality)
This property holds which windows are blocked by the modal widget.
This property only makes sense for windows. A modal widget prevents widgets in other windows from getting input. The value of this property controls which windows are blocked when the widget is visible. Changing this property while the window is visible has no effect; you must hide() the widget first, then show() it again.
By default, this property is Qt::NonModal.

CRichEditCtrl how to ignore a keypress?

i have a rich edit box in one of my dialog of MFC dialog based app.
it can only have numeric values.
Now what i am trying to do is dont allow user to enter a value greater then 4567899.
if user is entering numbers in the the rich edit box and by pressing the number key will make the value already enterd in text box greater then 4567899 then just make the app behave like no key is pressed or just ignore that key press.
I did some research and found that this can be done by EN_MSGFILTER event but i m not sure about that.
so this is the function
void CMyDialog::OnMsgfilterObjectid(NMHDR* pNMHDR, LRESULT* pResult)
{
char tempID[10];
MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
// TODO: The control will not send this notification unless you override the
// CDialog::OnInitDialog() function to send the EM_SETEVENTMASK message
// to the control with either the ENM_KEYEVENTS or ENM_MOUSEEVENTS flag
// ORed into the lParam mask.
// TODO: Add your control notification handler code here
*pResult = 0;
if((pMsgFilter->wParam >= 48) || pMsgFilter->wParam<=57) // check if 0-9 is pressed
{
m_objectIDInstance.GetLine(NULL,tempID); //m_objectIDInstance is a CRichEditCtrl
tempID[m_objectIDInstance.LineLength()] = '\0';
if ((atol(tempID) + (pMsgFilter->wParam-48)) > 4567899)
{
*pResult=1;
}
}
}
in OnInitDialog() i added following line:
m_objectIDInstance.SendMessage(EM_SETEVENTMASK, 0, ENM_KEYEVENTS);
Buts its not working so please if somebody can help or can suggest a different way to do what i am trying to implement.
Thanks
You seem to be sending the message to the dialog. It has to be sent to the edit control.
m_objectIDInstance.SendMessage(...)

Easy way to assign function keys to Dialog?

I have a MFC dialog and I would like to assign function keys to different methods. Is that possible?
For example I would like to type F9 and have the same result as pressing a button.
For Dialog Based application. Create a IDR_ACCELERATOR1 in resource editor for your dialog. And add the Key you wanted and create a Event for the Key for your dialog.
In sampledlg.h please add
HACCEL m_haccel;
In sampledlg.cpp In OnInitDialog() please add
m_haccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));
In sampledlg.cpp In PreTranslateMessage(MSG *pMsg) please add
if (m_haccel)
{
if ((::TranslateAccelerator(*this, m_haccel, pMsg)))
{
return(TRUE);
}
}
If you mean in the main dialog of a dialog based application, you can check
http://www.codeproject.com/Articles/37130/Implement-Accelerators-in-a-Dialog-Based-Applicati.aspx
If it's for dialogs in a doc/view application:
http://support.microsoft.com/kb/117500/en-us
http://support.microsoft.com/kb/222829/en-us
Easier than I thought. I don't know if this is the best solution but this is what I did:
BOOL MainDlg::PreTranslateMessage(MSG *pMsg)
{
if ( pMsg->message == WM_KEYDOWN)
{
if (( pMsg->wParam == VK_F9))
OnBnClickedButton1(); // Delete Item
}
return CDialog::PreTranslateMessage(pMsg);
}
Now, every time Function Key F9 is pressed function OnBClickedButton1() is called.

how to use ribbon category to switch view?

I want to use two ribbon category buttons to switch between two different views, but I found it can't add event handler to the button.
Is there any hint to solve this problem? Better if there is some sample, actually I'm new to MFC.
You could try hooking into this event?
AFX_WM_ON_CHANGE_RIBBON_CATEGORY
An option I have found successful was to subclass CMFCRibbonBar and override PreTranslateMessage and check for mouse clicks. Below are the steps I took which have thus far worked well.
Subclass CMFCRibbon - in my example I created CCustomRibbonBar
Override PreTranslateMessage, and add an int value to keep track of the tab
Create a custom windows message that your applications MainForm handles -WM_ACTIVE_RIBBON_TAB_CHANGED in my example
Inside of PreTranslateMessage check for Left Mouse Up event
In the event of a left mouse button up, let the Ribbon finish handling the message and then query the Active Category.
Post the active category to MainForm (or other form)
In your MainForm, handle the category and take into account that with most events the category will not have changed.
Then in my override I check for the mouse up event and retrieve the Active category
Inside Class Declaration
virtual BOOL PreTranslateMessage(MSG* pMsg);
int m_LastActiveCategory;
Inside Class Definition
BOOL CCustomRibbonBar::PreTranslateMessage(MSG* pMsg)
{
//If command was finishing a click
if(pMsg->message == WM_LBUTTONUP && pMsg->wParam == 0)
{
//Allow ribbon to handle itself first
BOOL result = CMFCRibbonBar::PreTranslateMessage(pMsg);
//Get new active tab
int activeTab = GetCategoryIndex(GetActiveCategory());
//If tab has changed, forward message
if(activeTab != m_LastActiveCategory)
{
//forward message to parent
::SendMessage(GetParentFrame()->GetSafeHwnd(),WM_ACTIVE_RIBBON_TAB_CHANGED,activeTab,0);
m_LastActiveCategory = activeTab;
}
return result;
}
//Otherwise handle like normal
return CMFCRibbonBar::PreTranslateMessage(pMsg);
}