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.
Related
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);
}
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.
}
I created a simple dialog with a label and edit box, then created a class, CInputDlg, added member variables for the label and edit box, and called it
CInputDlg dialog
dialog.m_label = TEXT("Enter a number:");
if (dialog.DoModal() == IDOK) {
// Do something
}
Now how do I display the text which is entered into the edit box?
Try WM_GETTEXT
http://msdn.microsoft.com/en-us/library/ms632627(v=VS.85).aspx
In the Handler for the OK button on the Dialog, you should get the TextBox.GetText(), and put it back into a public CString member m_InputString. Then, from the calling function, you can read dialog.m_InputString.
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);
}
I have an SDI application written in MFC. The frame is divided into 1 row and 2 columns using a splitter window. Below are details of Row and Column (R0C0 means Row#0 and Col#0)
R0C0 view is a CFormView with multiple input controls like text box, combo box etc.
R0C1 view is a CHtmlView that contains HTML content relavant to the control that has input focus in the R0C0
I am able to update the HTML content and also invoke Javascript functions through my MFC code.
Problem:
When user clicks on the R0C1, continaing CHtmlView, the focus is now on the html page. I wish to allow the user to tab out of R0C1 using the key board and return back to R0C0. Can you help with this please? The user can obviously click on the R0C0 view using mouse but we have a user who needs to use Keyboard for using this functionality.
Let me know if the question is not descriptive enough and I'll simplify it further.
Appreciate your time.
Thanks,
Byte
Try to overload CHtmlView::OnTranslateAccelerator. I have successfully used this trick to disable refresh with F5 key. Derive your own class from CHtmlView and overload
virtual HRESULT OnTranslateAccelerator(LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID);
like this:
HRESULT CMyHtmlView::OnTranslateAccelerator(LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID)
{
if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_TAB) != 0 )
{
// change focus
return S_OK;
}
return CHtmlView::OnTranslateAccelerator( lpMsg, pguidCmdGroup, nCmdID);
}