Good afternoon
I use a tabControl and a treeViewControl. I use "OnSelchangingTabcontrol(NMHDR *pNMHDR, LRESULT *pResult)" and in certain condition I want to prohibit the change of the selected item. How do I cancel the event?
I have the same problem for the treeViewControl.
Thanks
In the OnSelchangingTabcontrol() body after you check for the conditions do this:
if(/*erroneous condition*/)
{
*pResult = 1;
return;
}
The same thing applies to tree view event. Make sure you handle XX_CHANGING event, not XX_CHANGED
Related
I was hoping someone out there would help me with my predicament I ran into. Essentially I have a Checkbox and a RichEditControl next to each other. I want to be able to know when a user has clicked on my RichEditControl so i can send a message to my checkbox to flag it on and off.
At first i tried to overlay my checkbox with empty text to act as a "blank" background for my RichEditControl so i wouldn't have to worry about sending messages left and right. No matter what i tried the "blank" background would overlap the RichEditControl text and leave it completely blank.
I searched on here for some help and i found this which is exactly what I ran into. I understand what he is saying but don't have the knowledge to implement what they said.
Right now I'm playing around with EN_LINK to attempt to capture a message so i can tell my checkbox to flag itself.
BEGIN_MESSAGE_MAP(TempInit, CDialog)
ON_NOTIFY(EN_LINK, IDC_TempInitMsg, &TempInit::OnEnLinkTempinitmsg)
END_MESSAGE_MAP()
void TempInit::OnEnLinkTempinitmsg(NMHDR *pNMHDR, LRESULT *pResult)
{
ENLINK *pEnLink = reinterpret_cast<ENLINK *>(pNMHDR);
// TODO: Add your control notification handler code here
// TODO: Add your control notification handler code here
radioClicked = !radioClicked;
if (radioClicked == true)
{
GetParent()->SendMessage(WM_MYRADIOCLICKED, CHECKENABLED, 0);
}
else
{
GetParent()->SendMessage(WM_MYRADIOCLICKED, CHECKDISABLED, 0);
}
}
*pResult = 0;
}
I'm sorry in advance if this is totally the wrong way to go about this. I've been googling for a few hours and have come empty handed. If anyone has any other method please help me if possible. I can post more code if what i have above isn't enough.
Steven,
One way to go about this would be to handle the EN_MSGFILTER notification from the rich edit control. I can't provide you any code to show you how to do this off hand but here's the documentation for the Notification messages from that the Rich edit control generates. Simply handle it the same way your doing with your radio button.
This will check the check box when the Rich Edit Ctrl has the focus and untick
it when it losses the focus.
BEGIN_MESSAGE_MAP(TempInit, CDialogEx)
ON_EN_SETFOCUS(IDC_RICHEDIT21, &TempInit::OnEnSetfocusRichedit21)
ON_EN_KILLFOCUS(IDC_RICHEDIT21, &TempInit::OnEnKillfocusRichedit21)
END_MESSAGE_MAP()
void CMFCApplication1Dlg::OnEnSetfocusRichedit21()
{
CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK1);
pCheckBox->SetCheck(1);
}
void CMFCApplication1Dlg::OnEnKillfocusRichedit21()
{
CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK1);
pCheckBox->SetCheck(0);
}
I am moving Borderless DHtmlDialog of MFC with this method:
BOOL CMyDlg::preTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_LBUTTONDOWN)
{
PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( pMsg->pt.x, pMsg->pt.y));
return false;
}
return CDHtmlDialog::preTranslateMessage(pMsg);
}
But the problem is that it is moving but couldn't picking up any click event for tags and ids given in DHTML_EVENT_MAP.
Can any one please guide what is the main problem in this? Please help.
This is because DHTML_EVENT_MAP will not handle click events on tags.
MFC macros are not supposed to do that. You will need event sink in your code.
Refer Handling HTML Element Events
In a certain dialog I would like when the user presses the enter key for it to act as an "apply" button. So far I have at least been able to make the dialog not close upon pressing enter by overriding CWnd::PreTranslateMessage, so currently it just does nothing and I'm not sure how to send apply command from there.
Every dialog should have one and only one button with the BS_DEFPUSHBUTTON style, which indicates to the dialog that this is the button to activate with the Enter key. Usually this is the OK button, but you can make it the Apply button if you want to.
As Mark pointed out above the dialog manager already has all the logic built in to handle the Enter key by invoking the command associated with the default button. You can statically assign the BS_DEFPUSHBUTTON style or handle the DM_GETDEFID message.
The former is trivially easy and the latter is fairly simple to implement. Make sure you set the Default Button property to False for all buttons on your dialog. Now add a message handler for the DM_GETDEFID message. There is no dedicated macro for this message so you have to use the generic handler:
BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
...
ON_MESSAGE(DM_GETDEFID, OnGetDefId)
END_MESSAGE_MAP()
The message handler is equally simple and uses the default message handler signature:
LRESULT CMyDialog::OnGetDefId(WPARAM wParam, LPARAM lParam)
{
return MAKELRESULT(ID_APPLY, DC_HASDEFID);
}
The message handler must return a value whose high-order word contains DC_HASDEFID and the low-order word contains the control ID.
If you navigate over the controls of the dialog you will see that the Apply button has the typical default button visual cue while focus is not on another command button. Pressing Enter while a non-button control has the input focus invokes the default button's command handler. No additional code required.
If your intent is to handle the Enter key without dismissing the dialog, you may be going about it incorrectly. Please take a look at this MSDN article. While using PreTranslateMessage should work, it is not the best way to handle these types of events.
You'll need to handle the OnKeyDown message, and handle the VK_RETURN character inside that function.
void MyCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(nChar == VK_RETURN)
{
// Do Stuff
return;
}
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
Another way to overwrite the message.
BOOL CMyDialog::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_RETURN:
{
UINT nID = ::GetDlgCtrlID(pMsg->hwnd);
if (nID == ID_APPLY)
{
//DO YOUR STUFF HERE
}
}
break;
default:
break;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
Also, you don't need to use PreTranslateMessage if you are using ::OnKeyDown
I have 3 list control on one dialog box but only one is showing focus.
if i clicked on 2nd list control then focus disaappear from 1st one.
Means at a time only one list showing focus.
How to make focus remain on all list control on same dialog box?
I don't think that this is technically possible. 'Focus' is an attribute that can only be applied to an individual element.
Think of it in terms of 'focus' is the element that the user is currently interacting with. How would a user be expected to interact with 3 distinct elements at the same time?
As Brian says - focus can only be on one control at time. I'm guessing you are trying to change the other list controls based on the first list box. One way to do it is to associate a variable with each list control, like mListCtrl1, mListCtrl2. Then add a handler for the NM_CLICK event, and have some code like this:
void CTabTestDlg::OnNMClickList3(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = (LPNMITEMACTIVATE)(pNMHDR);
// TODO: Add your control notification handler code here
*pResult = 0;
UpdateData(true);
DWORD dwData = mListCtrl1.GetItemData(pNMItemActivate->iItem);
int max = mListCtrl2.GetItemCount();
for (int i=0;i<max;i++)
{
DWORD dwData2 = mListCtrl2.GetItemData(i);
if (dwData==dwData2)
{
mListCtrl2.SetItemState(i,LVIS_SELECTED,LVIS_SELECTED);
break;
}
}
UpdateData(false);
}
Note that I have the control set to "Always show selection", and "Single selection"
I have a dialog with a rich-text control. The dialog wants to intercept right-click events on the control; in some cases the dialog should do its own functionality and block the message reaching the control, in other cases it should let the control receive the message.
So I have:
ON_NOTIFY(EN_MSGFILTER, IDC_RICHTEXT, OnRichTextMsgfilter)
void CMyDialog::OnRichTextMsgfilter(NMHDR *pNMHDR, LRESULT *pResult)
{
MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
*pResult = 0;
if (pMsgFilter->msg == WM_RBUTTONUP)
{
if(...)
*pResult=1;
}
}
I step through the code and pResult is set when it should be, but the control still gets the message. Looking at MSDN it says:
If the control should process the
event, the message returns a zero
value. If the control should ignore
the event, the message returns a
nonzero value.
But the defined message handler signature has no return... I am assuming that's what *pResult is for. Is that not true? If so how do I achieve this?
So i've tried to reproduce this behavior in a simple dialog based app and i really can't -- however, i'm not sure what it is that intercepting the right button message is trying to solve.
That said the following code completely blocks the Left button mouse clicks in my testing (If this returns TRUE the control does not respond to left clicks - however focus will get set to the control on the initial click down and that is more a window manager issue than the control itself)
void CTestDlg::OnMsgfilterRichedit1(NMHDR* pNMHDR, LRESULT* pResult)
{
MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
if (pMsgFilter->msg == WM_LBUTTONUP || pMsgFilter->msg == WM_LBUTTONDOWN)
{
*pResult = TRUE;
return;
}
*pResult = FALSE;
}
If i change *pResult = TRUE to *pResult = FALSE then the left clicks start working again.
It could be that you want to catch and filter out the WM_RBUTTONDOWN rather than WM_RBUTTONUP to do what you intend, but since i'm unsure what functionality you are trying to filter out i can't say for sure.
The WM_RBUTTONDOWN is stil getting through...