|
MFC tests when you type, that is why it is stupid. If you have a number, highlight it and hit delete, you'll get a validation error. I ALWAYS roll my own validation, so as not to drive my users insane.
Christian
Hey, at least Logo had, at it's inception, a mechanical turtle. VB has always lacked even that... - Shog9 04-09-2002
During last 10 years, with invention of VB and similar programming environments, every ill-educated moron became able to develop software. - Alex E. - 12-Sept-2002
|
|
|
|
|
Christian Graus wrote:
MFC tests when you type
Really? Not only in UpdateData()? This was new to me, it must be limited to CEdit, as all other validations are triggered by UpdateData().
|
|
|
|
|
MFC *doesn't* test until DoDataExchange is called from UpdateData.
Tomasz Sowinski -- http://www.shooltz.com
*** Si fractum non sit, noli id reficere. ***
|
|
|
|
|
Hmmm.... I remember spending ages trying to stop it from popping up all the time, but when I did a quick test, it was not the case. I'm confused now, I wonder what I was doing at the time.....
Christian
Hey, at least Logo had, at it's inception, a mechanical turtle. VB has always lacked even that... - Shog9 04-09-2002
During last 10 years, with invention of VB and similar programming environments, every ill-educated moron became able to develop software. - Alex E. - 12-Sept-2002
|
|
|
|
|
what can I do? I have no time and this will semi-solve my problem, when I'd have finished this machine, I'll try to find out another way...
|
|
|
|
|
I found this
DDX_Check(pDX, IDC_SEX, m_bFemale);
DDX_Text(pDX, IDC_EDIT1, m_age);
if (m_bFemale)
DDV_MinMax(pDX, age, 0, m_maxFemaleAge);
else
DDV_MinMax(pDX, age, 0, m_maxMaleAge);
in the MSDN under "TN026: DDX and DDV Routines".
Seems you can easily use variables.
|
|
|
|
|
Hi Joan,
One way would be to derive your own class from CEdit. Add a member variable that holds the maximum value (which you can then dynamically change in your program) and handle the EN_CHANGE or WM_CHAR messages to check whether the modified string is out of range.
I have an example of this but it is at home (it only allows you to type in floating point numbers only). I can send it to you if you wish but I can only do this tonight.
Cheers
Adam.
www.beachwizard.com/travelogue[^]
"I spent a lot of my money on booze, birds and fast cars. The rest I just squandered"
George Best.
|
|
|
|
|
As I have no time, it would be great for me to receive that sample, all of you in codeproject are helping me a lot!
thank you very much!
|
|
|
|
|
Hi Joan,
Pop the following .h and .cpp files in your code. It should work (does for me anyway). You might have to play around with the checking of string lengths and conversions to make it more robust but the idea is there.
In class wizard, set the member variable of your edit box as a Control of type CIntEdit (call it m_wndEditBox or something) and then call m_wndEditBox.SetMaxInt(nMax) on the fly whenver you want (pref. initialise it in OnInitDialog in your dialog box, for example as the default is zero).
Note, the minimum acceptable integer value is zero but I am sure you could change the code as you see fit.
Any probs, givvus a shout
Best regards and good luck ,
Adam.
IntEdit.h
class CIntEdit : public CEdit<br />
{<br />
public:<br />
CIntEdit();<br />
<br />
public:<br />
<br />
public:<br />
<br />
<br />
public:<br />
void SetMaxInt(int nMax);<br />
int GetMaxInt();<br />
virtual ~CIntEdit();<br />
<br />
protected:<br />
int m_nMaxInt;<br />
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);<br />
<br />
DECLARE_MESSAGE_MAP()<br />
};
IntEdit.cpp
<br />
#include "stdafx.h"<br />
#include "IntEdit.h"<br />
<br />
#ifdef _DEBUG<br />
#define new DEBUG_NEW<br />
#undef THIS_FILE<br />
static char THIS_FILE[] = __FILE__;<br />
#endif<br />
<br />
<br />
CIntEdit::CIntEdit()<br />
{<br />
m_nMaxInt=0;<br />
}<br />
<br />
CIntEdit::~CIntEdit()<br />
{<br />
}<br />
<br />
<br />
BEGIN_MESSAGE_MAP(CIntEdit, CEdit)<br />
ON_WM_CHAR()<br />
END_MESSAGE_MAP()<br />
<br />
<br />
void CIntEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) <br />
{<br />
const int DEL=8;<br />
if((nChar<'0' || nChar>'9') && nChar!=DEL) return;<br />
CString strWndTxt="", strTemp="",strChar="";<br />
strChar=(TCHAR)nChar;<br />
<br />
int nStartChar=0, nEndChar=0, nLen=0, nVal=0;<br />
GetWindowText(strWndTxt);<br />
nLen=strWndTxt.GetLength()/sizeof(TCHAR);<br />
GetSel(nStartChar,nEndChar);<br />
strTemp=strWndTxt.Left(nStartChar)+strChar+strWndTxt.Right(nLen-nEndChar);<br />
TRACE(strTemp);<br />
<br />
nVal=_ttoi(strTemp);<br />
if(nVal<=m_nMaxInt)<br />
{<br />
CEdit::OnChar(nChar, nRepCnt, nFlags);<br />
}<br />
}<br />
<br />
int CIntEdit::GetMaxInt()<br />
{<br />
return m_nMaxInt;<br />
}<br />
<br />
void CIntEdit::SetMaxInt(int nMax)<br />
{<br />
m_nMaxInt=nMax;<br />
}
www.beachwizard.com/travelogue[^]
"I spent a lot of my money on booze, birds and fast cars. The rest I just squandered"
George Best.
|
|
|
|
|
IMHO OnChar is not the correct way to do this as your validation routine is totally bypassed when an entry is copiedpasted in from the clipboard. You are much better off using OnUpdate (EN_UPDATE) to handle validation in edit controls.
CPUA 0x5041
Sonork 100.11743 Chicken Little
"So it can now be written in stone as a testament to humanities achievments "PJ did Pi at CP"." Colin Davies
Within you lies the power for good - Use it!
|
|
|
|
|
You are spot on. I relied on discarding ctrl+V keystrokes but if I right click on the edit box, I have the option to paste in it.
Well spotted!
Adam.
www.beachwizard.com/travelogue[^]
"I spent a lot of my money on booze, birds and fast cars. The rest I just squandered"
George Best.
|
|
|
|
|
You COULD handle WM_PASTE also, this is where all clipboard pastes end up.
Just GetWindowText() the content into a local variable, call Default() , and validate the pasted text. If you want to revert to the old text you had before the insert, you can SetWindowText() it back from your local variable.
But EN_UPDATE is probably better.
|
|
|
|
|
Have you considered CEdit::SetLimitText ?
Never mind. I didn't read your post carefully enough.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Just replace the constant '3000' with a name of variable containing the dynamic limit:
DDV_MinMaxInt(pDX, m_vediVelocitat, 0, m_maxVelocitat);
Of course, you should set m_maxVelocitat to appropriate value before DoDataExchange is called.
As a side note, you can check 'number' flag in the edit properties invoked in dialog editor. This will block non-digit characters being typed. AFAIR, however, you can still paste anything into numeric edit, so DDV_ call is essential.
Tomasz Sowinski -- http://www.shooltz.com
*** Purgamentum init, exit purgamentum ***
|
|
|
|
|
Tomasz Sowinski wrote:
As a side note, you can check 'number' flag in the edit properties
And it fails miserably with a negative number. I think it is next to useless, and I would say that MS did not make their homework with regards to Edit controls.
Mostly useless stuff like IP edit YES, but nothing working for integers and floating points - that would give bad ratings.
|
|
|
|
|
jhwurmbach wrote:
And it fails miserably with a negative number.
I've got the impression that Joan is working with some kind of velocity, which probably is non-negative. In this case, ES_NUMBER may be usable, but DDV_ is still required.
Tomasz Sowinski -- http://www.shooltz.com
*** Purgamentum init, exit purgamentum ***
|
|
|
|
|
Take a look at my article at http://www.codeproject.com/tools/Colour.asp[^]. I use an subclassed edit control that limits the input between 0 and 255 using the EN_UPDATE notification message (NumEdit.cpp and NumEdit.h). This should give you an idea on one method of limiting user input without using DDV_*.
HTH
CPUA 0x5041
Sonork 100.11743 Chicken Little
"So it can now be written in stone as a testament to humanities achievments "PJ did Pi at CP"." Colin Davies
Within you lies the power for good - Use it!
|
|
|
|
|
#include "stdafx.h"
#include <iostream.h>
#include <windows.h>
#include <tchar.h>
#define ErrorHandler(s) _ErrorHandler(s, __FILE__, __LINE__)
void _ErrorHandler(LPCSTR lpszLocation, LPCTSTR lpszSrcFile, UINT nSrcLine)
{
LPVOID lpMsgBuf;
DWORD dwError = GetLastError();
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPSTR) &lpMsgBuf,
0,
NULL );
// Process any inserts in lpMsgBuf.
cout<<"ERROR @ "<<lpszLocation<<" : "<<'('<<dwError<<')'<<(LPCSTR)lpMsgBuf;
cout<<"SOURCE @ Line = "<<nSrcLine<<", File = "<<lpszSrcFile<<'\n';
// Free the buffer.
LocalFree( lpMsgBuf );
}
BOOL SetFileOwner(LPCTSTR lpszFileName, LPCSTR lpszAccount, LPCSTR lpszGroup)
{
PSECURITY_DESCRIPTOR pSD;
PSID pSID, pSIDGroup;
DWORD cbSID = 1024;
LPSTR lpszDomain;
DWORD cchDomainName = 80;
PSID_NAME_USE psnuType;
// Initialize a security descriptor.
pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
SECURITY_DESCRIPTOR_MIN_LENGTH); // defined in WINNT.H
if (pSD == NULL) {
ErrorHandler("LocalAlloc");
goto Cleanup;
}
if (!InitializeSecurityDescriptor(pSD,
SECURITY_DESCRIPTOR_REVISION)) { // defined in WINNT.H
ErrorHandler("InitializeSecurityDescriptor");
goto Cleanup;
}
// Retrieve the SID for User.
pSID = (PSID) LocalAlloc(LPTR, cbSID);
psnuType = (PSID_NAME_USE) LocalAlloc(LPTR, 1024);
lpszDomain = (LPSTR) LocalAlloc(LPTR, cchDomainName);
if (pSID == NULL || psnuType == NULL ||
lpszDomain == NULL) {
ErrorHandler("LocalAlloc");
goto Cleanup;
}
if (!LookupAccountName((LPSTR) NULL, // local name
lpszAccount,
pSID,
&cbSID,
lpszDomain,
&cchDomainName,
psnuType)) {
ErrorHandler("LookupAccountName");
goto Cleanup;
}
if (!IsValidSid(pSID))
{
ErrorHandler("IsValidSid");
goto Cleanup;
}
// Sets the owner to the SD
if (!SetSecurityDescriptorOwner(pSD, pSID, FALSE)) { // not a default SID
ErrorHandler("SetSecurityDescriptorOwner");
goto Cleanup;
}
// Retrieve the SID for Group.
cbSID = 1024;
pSIDGroup = (PSID) LocalAlloc(LPTR, cbSID);
if (pSIDGroup == NULL) {
ErrorHandler("LocalAlloc");
goto Cleanup;
}
if (!LookupAccountName((LPSTR) NULL, // local name
lpszGroup,
pSIDGroup,
&cbSID,
lpszDomain,
&cchDomainName,
psnuType)) {
pSIDGroup = (PSID)LocalReAlloc((HLOCAL) pSIDGroup, cbSID, LPTR);
lpszDomain = (LPSTR) LocalReAlloc((HLOCAL) lpszDomain, cchDomainName, LPTR);
if (pSIDGroup == NULL || lpszDomain == NULL) {
ErrorHandler("LocalReAlloc");
goto Cleanup;
}
if (!LookupAccountName((LPSTR) NULL, // local name
lpszGroup,
pSIDGroup,
&cbSID,
lpszDomain,
&cchDomainName,
psnuType)) {
ErrorHandler("LookupAccountName");
goto Cleanup;
}
}
if (!IsValidSid(pSIDGroup))
{
ErrorHandler("IsValidSid");
goto Cleanup;
}
// Sets the group to the SD
if (!SetSecurityDescriptorGroup(pSD, pSIDGroup, FALSE)) { // not a default SID
ErrorHandler("SetSecurityDescriptorGroup");
goto Cleanup;
}
// Use the new SD as the file's security info.
if (!SetFileSecurity(lpszFileName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, pSD)) {
ErrorHandler("SetFileSecurity");
goto Cleanup;
}
return TRUE;
Cleanup:
FreeSid(pSID);
FreeSid(pSIDGroup);
if(pSD != NULL)
LocalFree((HLOCAL) pSD);
if(psnuType != NULL)
LocalFree((HLOCAL) psnuType);
if(lpszDomain != NULL)
LocalFree((HLOCAL) lpszDomain);
return FALSE;
}
int _tmain(int argc, TCHAR *argv[], TCHAR *envp[])
{
if (argc < 4) {
cout<<"ERROR @ main : Not enough parameters\n";
return 0;
}
TCHAR tszFileName[MAX_PATH];
char szUserName[256];
char szGroupName[256];
_tcscpy(tszFileName, argv[1]);
#if defined(_UNICODE) || defined(UNICODE)
if (!WideCharToMultiByte(CP_ACP, 0, argv[2], -1, szUserName, 256, NULL, NULL)) {
ErrorHandler("WideCharToMultiByte");
return 0;
}
if (!WideCharToMultiByte(CP_ACP, 0, argv[3], -1, szGroupName, 256, NULL, NULL)) {
ErrorHandler("WideCharToMultiByte");
return 0;
}
#else
strcpy(szUserName, argv[2]);
strcpy(szGroupName, argv[3]);
#endif
if (!SetFileOwner(tszFileName, szUserName, szGroupName)) {
cout<<"Operation Failed!\n";
return 0;
}
cout<<"Operation Succeeded!\n";
return 0;
}
=======================================================================
This program can set file and dir owner for "administrator"
or "administrators", but can't set for other user, else return
the "ERROR_INVALID_OWNER(1703L)"...
Why??? Please help me ~!!!
=======================================================================
|
|
|
|
|
This[^] is just for you
...if you're under 8 or younger. Chris Maunder, the Lounge
|
|
|
|
|
Thank you very much!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
|
how to calculate a runing time of program in "TICKS", in which computer calculates time of every thing. i m using simple Turbo c++.
|
|
|
|
|
ummmm
dwStartTickCount = GetTickCount(); // at the start
dwEndTickCount = GetTickCount(); //at the end
dwTicksToRun = dwEndTickCount - dwStartTickCount;
???
"... and so i said to him ... if it don't dance (or code) and you can't eat it either f**k it or throw it away" biz stuff about me
|
|
|
|
|
How to make a license file which makes the application expire after a specific date, and also how to stop copying the .exe file.
|
|
|
|
|
I'm sorry, but you're basically asking for someone to write you an article. You should post such questions to the article suggestions forum.
Do you know how to open and close a text file ? Use the registry ? Find out the current date/time from the system ? How do YOU think such a system would work ?
There is no way to stop people from copying a file.
Christian
Hey, at least Logo had, at it's inception, a mechanical turtle. VB has always lacked even that... - Shog9 04-09-2002
During last 10 years, with invention of VB and similar programming environments, every ill-educated moron became able to develop software. - Alex E. - 12-Sept-2002
|
|
|
|
|
Christian Graus wrote:
There is no way to stop people from copying a file
which is probably a good thing, else it'd be stuck in d:\projects\myapp\debug all the time. Hard to distribute.
Signature space for rent. Apply by email to....
|
|
|
|
|