I have my own class (CMyEdit) subclassed from CEdit with own validation procedure.
I hook events ON_CHAR and ON_UPDATE and validate user input.
If the input is valid, attribute CMyEdit::isOk is switched to true. CMyEdit confirms validity during each change of EditBox content.
Dialog could confirm validity by CMyEdit::isOk.
I have overridden CEdit::SetWindowText()
inline void CMyEdit::SetWindowText(LPCTSTR lsText)
{
CEdit::SetWindowText(lsText);
Validate(); //set isOk true or false
}
But if dialog uses DDX_Text, no method is running (Nor EN_CHANGE, neither SetWindowText).
The same problem is, when user put value from clipboard (WM_PASTE).
How to hook this change of EditBox content?
Related
I have a property sheet (CPropertySheet derived class) and its pages (CPropertyPage derived class) in CView derived view class. I need to get notice at CView derived class when the property page changes.
In my case, handling the PSN_SETACTIVE notification will not work.
The problem is by changing the page I need to update the data in the page from one resource. If that resource is not active then I need to close the view and restart the view again.
CPropertySheet does not receive information about tab changes.
PSN_SETACTIVE and PSN_KILLACTIVE is sent to CPropertyPage instead. You have to handle these messages in each PropertyPage when tab is selected/un-selected.
In MFC you can handle this as follows:
class CMyPropertyPage: public CPropertyPage
{
BOOL OnSetActive();
BOOL OnKillActive();
...
};
BOOL CMyPropertyPage:OnSetActive()
{
BOOL res = CPropertyPage::OnSetActive();
TRACE("CMyPropertyPage tab selected\n");
return res;
}
BOOL CMyPropertyPage:OnKillActive()
{
BOOL res = CPropertyPage::OnKillActive();
TRACE("CMyPropertyPage tab unselected\n");
return res;
}
See also:
WinAPI property sheet
CPropertyPage::OnSetActive
To send notification to CMyView, you will have to find the handle to your target and pass the message.
Question/Problem: I have an edit control (text box) that the user enters a username into. I am attempting to compare the username entered to the ones listed in my List Control. If the username given matches, my button's text should change from Create User to Update User.
My problem is in finding the correct event/time to compare the strings, without creating an infinite loop.
What I have tried: I have tried using the edit control events EN_CHANGE and EN_UPDATE. Both of these events cause stack-overflow exception or an infinite loop. I thought that one of these events would be called every time something is typed or the backspace was used within my edit control.
In my EN_CHANGE / EN_UPDATE event, I compare the username strings and set the button's text. With either event, it is called infinite times:
void Users::OnEnUpdateLoginName() //EN_UPDATE Event
{
bool match = false;
//Compare the edit control text with each List Control text.
for(int i = 0; i<m_UserList.GetItemCount(); i++)
{
if(strcmp(m_UserList.GetItemText(i,0),m_loginName)==0)
match = true;
}
//If the usernames match, change the button's text to "Update User"
if(match)
{
CWnd *currentSelection = GetDlgItem(TXTC_LOGIN_NAME);
currentSelection->SetWindowTextA("Update User");
}
else
{
CWnd *currentSelection = GetDlgItem(TXTC_LOGIN_NAME);
currentSelection->SetWindowTextA("Create User");
}
}
.
If the text in red matches, change the text of the button highlighted in blue.
Should I be using a different event to validate the string in real-time as the user types?
My code had two issues. I needed to use UpdateData, so that data for all my dialog controls would be current. I also was updating the wrong variables. Thanks #rrirower
How do I get cursor when dialog is start at OnInitDialog function,
without user to move click it, like as follow pic
enter link description here
Other problem is, when the editbox already fill with text, how do I select the text ?
On OnInitDialog function, I see as follow description,
// return TRUE unless you set the focus to a control
so I define a variable to the editbox, the set focus on it,
then return false in OnInitDialog function.
BOOL CInputTestPoint::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: 在此加入額外的初始化
m_editTestPointName.SetFocus();
//return TRUE; // return TRUE unless you set the focus to a control
return false;
// EXCEPTION: OCX 屬性頁應傳回 FALSE
}
For select whole text method is as follow
define CEdit to the edit box and m_editTestPointName.SetSel(0, strTestPointName.GetLength(), true);
((CEdit *)GetDlgItem(IDC_EDIT_INPUT_TP))->SetSel(0, strTestPointName.GetLength(), true);
I'm using qt-creator to build a little QT application.
I have a main window where I have some controls like a "new contact" button.
Pressing the button a QDialog is shown, it contains 3 line edits: name, mobile and email.
The dialog is shown through the Signal/Slot system. It works fine but I want to create a Contact object when OK is clicked and I want to give back that Contact to my main window in order to put it in a QList created in the main window code.
The approach is:
QMainWindow -> new contact -> QDialog is shown
QDialog -> ok -> QMainWindow
Should I pass the QList from the main window to the QDialog as argument or there is a best way?
Should I pass the QList from the main window to the QDialog as argument or there is a best way?
In my opinion, best would be a custom QDialog subclass with three QLabels and 3 QLineEdits.
The labels would get the following type of values:
Label 1: name
Label 2: mobileNumber
Label 3: email
You would use then QLabels and QLineEdits to display them with the input coming from the user.
Then, as your program probably already does, just handle the "accept" event respectively. You could use the following method to retrieve the text entered by the end user:
text : QString
This property holds the line edit's text.
Setting this property clears the selection, clears the undo/redo history, moves the cursor to the end of the line and resets the modified property to false. The text is not validated when inserted with setText().
The text is truncated to maxLength() length.
By default, this property contains an empty string.
Then, in the handler of the accepted signal, you could call three accessor methods, like:
QString name() const { return nameLineEdit->text(); }
QString mobileNumber() const { return mobileNumberLineEdit->text(); }
QString email() const { return emailLineEdit->text(); }
You could also store that in a dedicated structure depending on you build up your data representation, so the structure would be something like this:
struct Contact {
QString name;
QString mobileNumber;
QString email;
};
and then you would have the accessor for that as follows
Contact contact() const;
Make a subclass of QDialog. Call Yourclass::exec() to show the dialog (exec is a function in QDialog), then afterwards Yourclass::contactDetails() to get them. contactDetails is a perfectly ordinary member function that you have to write.
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);
}