[SOLVED] BUG: Strange edit control behaviour? |
Post Reply |
Author | ||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
Posted: 19 December 2008 at 6:31am |
|
Hi;
I created my own CXTPReportRecordItemText derived control and replaced OnEditChanging(). Lets assume the edit control contains 'AAAAA' on begin edit. The user is only allowed to enter alphabetic chars [A-Z] in uppercase letters. So I check the rstrNewText parameter of OnEditChanging against a regex pattern and return FALSE if this check fails. Normally I expect the edit control to ignore the entered char and keep the caret at the same position, but this is false, the caret is moved on to the next char. I believe that in CXTPReportInplaceEdit::OnEnChange() it's to late to store the current caret position and/or selection, because of the possibility to cancel the change completely - as in my case.
(I marked the questionable part in bold letters). How can this be fixed? |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
No ideas, how to fix this?
|
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
Hi,
if "Lets assume the edit control contains 'AAAAA' on begin edit. The user is only allowed to enter alphabetic chars [A-Z] in uppercase letters.
Lets assume the edit control contains 'AAAAA' on begin edit. The user is only allowed to enter alphabetic chars [A-Z] in uppercase letters. " then all you need to do for this case - set UPPER CASE editbox style |
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Hi;
I only simplified the description. The real world application has a complex regex pattern to inplace check the input. If it were that simple I would not have posted it. So whenever the regex pattern check fails I don't want the edit control to move the caret to the next position (in case the user [partially] overwrites an allready contained edit text). |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
OK - just clarify your logic. Suppose your user entry {symbol1,symbol2,...symbolN} sequence. Let's only symbolN is invalid. Are you like to keep {symbol1,symbol2,...symbolN-1} sequence or cancel all N entry symbols?
|
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Hi;
I want to keep all valid entries. So best would be to ignore the false input symbolN. Succeeding symbols should also be kept in place (when overwrite mode is on). |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
The proper cursor control action can't be taken in OnEnChange() function.
Suppose your OnEditChanging((XTP_REPORTRECORDITEM_ARGS*) this, strValNew) will act with 2 rulesstrValNew.Replace( "#", "@");strValNew.Replace( "?", "");and return TRUE;
For 1st case of replace current cursor action is proper, for second - need to move it on one pos back.
How you separete such cases in CXTPReportInplaceEdit::OnEnChange() function? I guess your derived OnEditChanging function should care about this back cursor move
|
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Hi;
Your suggestion isn't possible because * I can't create my own inplace edit control to be used by the report control (compared to property grid where this control is changable by the user). This would be my preferred solution. * m_strText_prev is private member of CXTPReportInplaceEdit and I need the string to be set in case an error occures while typing and the regex pattern check fails. But perhaps I find a better way to handle the state inbetween edit changes. I found XTP_NM_REPORT_PREVIEWKEYDOWN message, but this is somehow brute force... |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
1 - you did not answer my question
2 - you don't need m_strText_prev if your OnEditChanging return FALSE and strValNew not modified (means if your regex failed - restore passed strValNew and return FALSE) - in other case you will take full control
|
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Sorry I missed your question. Maybe because I do not change any characters in strValNew. If an error occures I only want to return FALSE and leave everything as is. So also the cursor should stay at the 'error position'. That's my initial problem, but I think you indirectly turned me to a possible solution. But it's a hack anyway...
About custom edit control, see also my post I wrote a few days ago. |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
Well - for your (non-smart case - means your parser - regex not fixing errors and return false instead) you can try this code void CXTPReportInplaceEdit::OnEnChange(){ if (m_bSetWindowText || !pControl || !pItem) return;CString strValue, strValNew; GetWindowText(strValue); strValNew = strValue; BOOL bCommit = pItem->OnEditChanging((XTP_REPORTRECORDITEM_ARGS*) this, strValNew);//test case for Forum discussion (Topic: BUG: Strange edit control behaviour? - 19 December 2008) //int iRep1 = strValNew.Replace("#", "@"); //int iRep2 = strValNew.Replace("?", ""); //if (iRep1 > 0 || iRep2 > 0) //{ // bCommit = FALSE; // strValNew = strValue; //}//test case for Forum discussion if (!bCommit || strValNew != strValue){ int nSelStart = 0, nSelEnd = 0;GetSel(nSelStart, nSelEnd); //test case for Forum discussion if (strValNew != strValue){ SetWindowText(strValNew); int k(0); for (int j = 0; j < strValue.GetLength(); j++){ if (strValNew[j] != strValue[j]){ k = j; break;} } SetSel(k, k); } else{ SetWindowText(m_strText_prev); SetSel(nSelStart -1, nSelEnd - 1); } //test case for Forum discussion // SetWindowText(bCommit ? strValNew : m_strText_prev); // SetSel(nSelStart, nSelEnd); } else{ m_strText_prev = strValue; } } Try to use it with your derived class and confirm success please |
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Ok;
I'll try it tomorrow and come back with the result. Nevertheless it results in a change of the core toolkit source. So I ask whether it will go into the next release of the toolkit on success or not? Meanwhile, thanks for your valued help! |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
Sure I will change the toolkit code. Try to test also the case you do smart validation and change smth inside your derived code - check how logical will be the resulted cursor position
|
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Ok!
Do you have plans to enable custom inplace edit controls too? We will need several mask edit control types in report controls of our software. |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Hi;
I tried your solution and it partially works. Two issues are not solved: 1. The user selects the whole text in the edit control and presses a key that is not accepted by the regex pattern. Then in your solution, the whole selection is cleared and the cursor is moved to the beginning of the text. This is also true for partially selected text. Other edit controls have a different behaviour: in this case, the edit control selection is kept the same. (This was my first problem when implementing this 'custom' edit task). 2.
What if strValNew is shorter than strValue? Wouldn't this lead to access violations? BTW: You didn't answer my question about custom edit controls in future releases... |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
Well - let's extend the concept to cover your copy operation Now we have different reactions for test case. Suppose your validation reject the string modification when string has "666666" pattern. It means that for key by key entry validation will allow to input "66666" and will stop on next "6" BUT if user PASTE "666666" as one Ctrl+V operation - all operation will rejected. This is that updated case covered. Try and give me your feedback
void CXTPReportInplaceEdit::OnEnChange()
{ if (m_bSetWindowText || !pControl || !pItem) return; CString strValue, strValNew; GetWindowText(strValue); strValNew = strValue; int kOld(0); if (m_strText_prev != strValue) { for (int j = 0; j < min(strValue.GetLength(), m_strText_prev.GetLength()); j++) { if (m_strText_prev[j] != strValue[j]) { kOld = j; break; } } } BOOL bCommit = pItem->OnEditChanging((XTP_REPORTRECORDITEM_ARGS*)this, strValNew); //Test cases for Forum discussion (Topic: BUG: Strange edit control behaviour? - 19 December 2008) //test case for key entry rejected by OnEditChanging handler //int iRep1 = strValNew.Replace("#", "@"); //int iRep2 = strValNew.Replace("?", ""); //if (iRep1 > 0 || iRep2 > 0) //{ // bCommit = FALSE; // strValNew = strValue; //}//test case for paste operation rejected by OnEditChanging handler //if (strValNew.Find("666666") > - 1) //{ // bCommit = FALSE; // strValNew = strValue; //}//test case for Forum discussion if (!bCommit || strValNew != strValue){ int nSelStart = 0, nSelEnd = 0;GetSel(nSelStart, nSelEnd); //test case for Forum discussion if (strValNew != strValue) //it means that bCommit is TRUE{ SetWindowText(strValNew); int k(0); for (int j = 0; j < min(strValue.GetLength(), strValNew.GetLength()); j++){ if (strValNew[j] != strValue[j]){ k = j; break;} } SetSel(k, k); } else //it means that bCommit is FALSE - need rollback{ SetWindowText(m_strText_prev); //SetSel(nSelStart -1, nSelEnd - 1);SetSel(kOld, kOld); //Cursor position before 1st OnEditChanging - handler - modified symbol} //test case for Forum discussion //MD - old code << // SetWindowText(bCommit ? strValNew : m_strText_prev); // SetSel(nSelStart, nSelEnd); //MD - old code >> } else{ m_strText_prev = strValue; //Normal (default) cursor positioning} } |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
btw - why you don't complain about non-supported Ctrl+A action?
You can modify OnChar function adding in the end few lines:
void CXTPReportInplaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{ ........................................... if (nChar == 1 && nFlags == 30) //Ctrl+A case{ SetSel(0, -1); } CEdit::OnChar(nChar, nRepCnt, nFlags); } |
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Hi; As I told in one of my previous posts, our company guidelines do not allow to change regular toolkit code, to avoid additional work and possible 'hidden' failures when new toolkit releases are available. We're using the toolkit since version 2.x and in the past we had to fix several bugs that came from modifying the core toolkit source. Today I dig into the CXTPReportRecordItem class to eventually find another solution for our editing issue, but until now with no success |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
|
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
>>the whole selection is cleared and the cursor is moved to the beginning of the text
btw - this is a standard reaction - e.g. C# System.Windows.Forms.MaskedTextBox()
if you select previous (validated) value and paste smth wrong - all selection clear and value set to default (initial - e.g. empty or prompt)
|
||
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
Hey, finally I make a control which recover previous selection if OnEditChanging not commit. Please try it and keep me updated
void CXTPReportInplaceEdit::OnEnChange(){ if (m_bSetWindowText || !pControl || !pItem) return;CString strValue, strValNew; GetWindowText(strValue); strValNew = strValue; //recover previous selection by diff between old and new text - compare from the start and from the end int kO = strValue.GetLength(); int kP = m_strText_prev.GetLength(); int K = min(kO, kP); int kOld(0); int kOldEnd(kP); if (m_strText_prev != strValue){ for (int j = 0; j < K; j++){ if (m_strText_prev[j] != strValue[j]){ kOld = j; break;} } for (int j = 1; j <= K; j++){ if (m_strText_prev[kP - j] != strValue[kO - j]){ kOldEnd = kP + 1 - j; break;} } } BOOL bCommit = pItem->OnEditChanging((XTP_REPORTRECORDITEM_ARGS*) this, strValNew);//Test cases for Forum discussion (Topic: BUG: Strange edit control behaviour? - 19 December 2008) //test case for key entry rejected by OnEditChanging handler //int iRep1 = strValNew.Replace("#", "@"); //int iRep2 = strValNew.Replace("?", ""); //if (iRep1 > 0 || iRep2 > 0) //{ // bCommit = FALSE; // strValNew = strValue; //}//test case for paste operation rejected by OnEditChanging handler //if (strValNew.Find("666666") > - 1) //{ // bCommit = FALSE; // strValNew = strValue; //}//test case for Forum discussion if (!bCommit || strValNew != strValue){ int nSelStart = 0, nSelEnd = 0;GetSel(nSelStart, nSelEnd); int kN = strValNew.GetLength(); int kk = min(kO, kN); if (strValNew != strValue) //it means that bCommit is TRUE{ SetWindowText(strValNew); int k(kk - 1); for (int j = 0; j < kk; j++){ if (strValNew[j] != strValue[j]){ k = j; break;} } SetSel(k, k); } else //it means that bCommit is FALSE - need rollback{ SetWindowText(m_strText_prev); SetSel(kOld, kOldEnd); if (nSelStart == kO && nSelEnd == kO && kP < kO)SetSel(nSelStart, nSelEnd); if (nSelStart == 1 && nSelEnd == 1 && kP < kO)SetSel(0, 0); } } else{ m_strText_prev = strValue; //Normal (default) cursor positioning} } |
||
mgampi
Senior Member Joined: 14 July 2003 Status: Offline Points: 1201 |
Post Options
Thanks(0)
|
|
Hi;
I tried it and now it works as expected! But I'm still insitent that a customizable edit control would be a requirement for the report control. Thanks for you help! |
||
Martin Product: Xtreme Toolkit v 22.1.0, new Projects v 24.0.0 Platform: Windows 10 v 22H2 (64bit) Language: VC++ 2022 |
||
Post Reply | |
Tweet
|
Forum Jump | Forum Permissions You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum |