flynny
asked on
restricting edit field in tree control to set number of characters
Hi all,
i have a tree control, which displays some visual information. One of the fields ia a character shotcut associated with the information this is displayed in the format
KEY:M
for example, when the user edits this text, i can strip away the KEY: no problem so that all that remains is the char. the problem is th user can still type as many charatcers as they want and i want to restict this.
i would like to restrict the edit field to be one character. is this possible? also all of these keys will be captial so if a user enters m i would like to convert this to M. how would i do this?
Many thanks for the help
i have a tree control, which displays some visual information. One of the fields ia a character shotcut associated with the information this is displayed in the format
KEY:M
for example, when the user edits this text, i can strip away the KEY: no problem so that all that remains is the char. the problem is th user can still type as many charatcers as they want and i want to restict this.
i would like to restrict the edit field to be one character. is this possible? also all of these keys will be captial so if a user enters m i would like to convert this to M. how would i do this?
Many thanks for the help
ASKER
thats great itsme, this will be exactly what i need. i'm doing something wrong though.
when an edit is detected (i.e. when the rename button is pressed in the tree on an item) i call a mehtod DoLabelEdit. The class I'm using etends CTreeCtrl.
i then create edit control
CEdit* pEdit = GetEditControl();
pEdit.LimitText(1); //it get to here and crashes with an access violation
when it crashes i points me to the AFXWIN2.INL and to the line which reads
{ ASSERT(::IsWindow(m_hWnd)) ; return (int)::SendMessage(m_hWnd, EM_LIMITTE XT, nChars, 0); }
any ideas what the prob could be.
many thanks matt.
when an edit is detected (i.e. when the rename button is pressed in the tree on an item) i call a mehtod DoLabelEdit. The class I'm using etends CTreeCtrl.
i then create edit control
CEdit* pEdit = GetEditControl();
pEdit.LimitText(1); //it get to here and crashes with an access violation
when it crashes i points me to the AFXWIN2.INL and to the line which reads
{ ASSERT(::IsWindow(m_hWnd))
any ideas what the prob could be.
many thanks matt.
>>>> pEdit.LimitText(1);
pEdit is a pointer which must be tested for not being NULL. As far as I remember it is only different from NULL *after* you called DoLabelEdit(); (but I am no sure). To understand why, imagine there is only one edit field for the tree control, initial hidden in some corner all sizes 0. If calling DoLabelEdit() they activate the edit field and move it exactly to match the cell to edit. Got it?
Regards, Alex
pEdit is a pointer which must be tested for not being NULL. As far as I remember it is only different from NULL *after* you called DoLabelEdit(); (but I am no sure). To understand why, imagine there is only one edit field for the tree control, initial hidden in some corner all sizes 0. If calling DoLabelEdit() they activate the edit field and move it exactly to match the cell to edit. Got it?
Regards, Alex
>>>> pEdit is a pointer which must be tested for not being NULL
So, the statement actually is
if (pEdit != NULL)
{
pEdit->LimitText(1); // note the arrow
}
So, the statement actually is
if (pEdit != NULL)
{
pEdit->LimitText(1); // note the arrow
}
ASKER
ok i've changed it to this and the pEdit being returned is NULL as its bypassing the LimitText call.
any ideas why?
any ideas why?
ASKER
sorry its me i missed the comment above.
so if the edit field is unobtainable before the doeditlabel method is called is there no way i can get hold of it before the edit?
so if the edit field is unobtainable before the doeditlabel method is called is there no way i can get hold of it before the edit?
>>>> ASSERT(::IsWindow(m_hWnd)) ;
>>>> when it crashes i points me to the AFXWIN2.INL
I assume you got an 'assertion' rather than a crash. An assertion only happens in debug mode and tells you that a precondition for a system function doesn't apply. Here, it means that the edit window doesn't have a window associated yet. If you get this assertion after you called DoLabelEdit, you may need some delay between DoLabelEdit and SetLimitText cause they may have moved creation of the edit field to some PostMessage activity rather than doing it when you are calling DoLabelEdit. That is bad, cause you would need a delay as well, i. e. you cannot make the LimitText in the current handler function. The fasted would be to setup the OnTimer() handler for that class and invoke a timer instead of calling LimitText:
if (pEdit != NULL)
{
if (!IsWindow(pEdit->m_hWnd))
{
SetTimer(99, 100); // set a timer with id 99 and for next 100 msec
}
else
pEdit->LimitText(1);
}
in the OnTimer function you would do:
afx_msg void MyDialog::OnTimer(UINT nIDEvent)
{
if (nIDEvent == 99)
{
CEdit* pEdit = m_treeCtrl.GetEditControl( );
if (pEdit != NULL && IsWindow(pEdit->m_hWnd))
{
pEdit->LimitText(1);
KillTimer(99);
}
/* else the timer would try again */
}
}
Note, the SetTimer was called in the context of the dialog or view rather than from the tree control. If you are in a handeler of the tree control you may get your parent class and do the above in a member function of that class.
MyDialog* pParent = (MyDialog*)GetParent();
if (pParent != NULL)
pParent->setupTreeEditCont rol();
>>>> when it crashes i points me to the AFXWIN2.INL
I assume you got an 'assertion' rather than a crash. An assertion only happens in debug mode and tells you that a precondition for a system function doesn't apply. Here, it means that the edit window doesn't have a window associated yet. If you get this assertion after you called DoLabelEdit, you may need some delay between DoLabelEdit and SetLimitText cause they may have moved creation of the edit field to some PostMessage activity rather than doing it when you are calling DoLabelEdit. That is bad, cause you would need a delay as well, i. e. you cannot make the LimitText in the current handler function. The fasted would be to setup the OnTimer() handler for that class and invoke a timer instead of calling LimitText:
if (pEdit != NULL)
{
if (!IsWindow(pEdit->m_hWnd))
{
SetTimer(99, 100); // set a timer with id 99 and for next 100 msec
}
else
pEdit->LimitText(1);
}
in the OnTimer function you would do:
afx_msg void MyDialog::OnTimer(UINT nIDEvent)
{
if (nIDEvent == 99)
{
CEdit* pEdit = m_treeCtrl.GetEditControl(
if (pEdit != NULL && IsWindow(pEdit->m_hWnd))
{
pEdit->LimitText(1);
KillTimer(99);
}
/* else the timer would try again */
}
}
Note, the SetTimer was called in the context of the dialog or view rather than from the tree control. If you are in a handeler of the tree control you may get your parent class and do the above in a member function of that class.
MyDialog* pParent = (MyDialog*)GetParent();
if (pParent != NULL)
pParent->setupTreeEditCont
>>>> is there no way i can get hold of it before the edit?
Actually if you call DoLabelEdit the edit is only created. So you can set the LimitText after calling DoLabelEdit without any problem (cause the user needs at least 1 second before typing any text). The only problem would be if the pEdit is not a valid window *after* if you caleld GetEditControl after DoLabelEdit. Then, you need the timer solution.
Actually if you call DoLabelEdit the edit is only created. So you can set the LimitText after calling DoLabelEdit without any problem (cause the user needs at least 1 second before typing any text). The only problem would be if the pEdit is not a valid window *after* if you caleld GetEditControl after DoLabelEdit. Then, you need the timer solution.
>>>> cause the user needs at least 1 second before typing any text
The real reason is that as long as you are in a handler function no other message was processed. So, the pEdit->LimitText would happen prior to handling any WM_KEYDOWN/WM_CHAR/WM_KEYU P message.
The real reason is that as long as you are in a handler function no other message was processed. So, the pEdit->LimitText would happen prior to handling any WM_KEYDOWN/WM_CHAR/WM_KEYU
ASKER
hi itsme,
ok i'm trying to add the timer however its saying that
error C2660: 'SetTimer' : function does not take 2 parameters
heres what i've done, in my CEditTreeCtrl . h file i have added the afx_msg
afx_msg void OnEditTimer(UINT nIDEvent);
and in my beginlabeledit funci call
SetTimer( 99, 100 );
with the function
afx_msg void CEditTreeCtrl::OnEditTimer (UINT nIDEvent)
{
if (nIDEvent == 99)
{
CEdit* pEdit = CTreeCtrl::GetEditControl( );
if (pEdit != NULL && IsWindow(pEdit->m_hWnd))
{
pEdit->LimitText(1);
KillTimer(99);
}
/* else the timer will try again */
}
}
am i doing somehing wrong here? i've tried adding in a hwnd and callbak too but with no luck. any ideas?
thanks matt.
ok i'm trying to add the timer however its saying that
error C2660: 'SetTimer' : function does not take 2 parameters
heres what i've done, in my CEditTreeCtrl . h file i have added the afx_msg
afx_msg void OnEditTimer(UINT nIDEvent);
and in my beginlabeledit funci call
SetTimer( 99, 100 );
with the function
afx_msg void CEditTreeCtrl::OnEditTimer
{
if (nIDEvent == 99)
{
CEdit* pEdit = CTreeCtrl::GetEditControl(
if (pEdit != NULL && IsWindow(pEdit->m_hWnd))
{
pEdit->LimitText(1);
KillTimer(99);
}
/* else the timer will try again */
}
}
am i doing somehing wrong here? i've tried adding in a hwnd and callbak too but with no luck. any ideas?
thanks matt.
ASKER
ok if i set the third param to NULL, then it compiles however (after adding break points to the timerfunc) it doesn't triggerr the timer?
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
hi its me doing it this way gives the error
error C2664: 'SetTimer' : cannot convert parameter 3 from 'void (unsigned int)' to 'void (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,unsigned long)'
do i need to use the following?
void CALLBACK MyTimerProc(
HWND hwnd,
UINT uMsg,
UINT idEvent,
DWORD dwTime )
error C2664: 'SetTimer' : cannot convert parameter 3 from 'void (unsigned int)' to 'void (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,unsigned long)'
do i need to use the following?
void CALLBACK MyTimerProc(
HWND hwnd,
UINT uMsg,
UINT idEvent,
DWORD dwTime )
CEdit* pEdit = tree.GetEditControl();
Then, you may call functions like CEdit::LimitText to limit the text input given.
>>>> if a user enters m i would like to convert this to M.
You may do that after the the field was changed, e. g. by calling SetItemText. You would need a handler for TVN_ENDLABELEDIT to get notified.
Regards, Alex