Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Numeric keypad 0

39 views
Skip to first unread message

Stephen Wolstenholme

unread,
Mar 25, 2013, 11:40:55 AM3/25/13
to
Has anyone seen a problem with isalnum not seeing the zero key on the
numeric keyboard? Num lock is on. The zero key on the QWERTY keyboard
works. Adding char 96 to the test works but it should not be needed.

Steve

--
EasyNN-plus. Neural Networks plus. http://www.easynn.com
SwingNN. Forecast with Neural Networks. http://www.swingnn.com
JustNN. Just Neural Networks. http://www.justnn.com

R.Wieser

unread,
Mar 25, 2013, 4:52:43 PM3/25/13
to
Stephen,

Have you already checked what data you are feeding to that "isalnum"
function (coming from the numeric keyboard) ?

Most likely the problem is related to the method/function you are using to
retrieve the data from the keyboard, not to the "isalnum" function.

Regards,
Rudy Wieser


-- Origional message:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
tjr0l8toleul2nqrt...@4ax.com...

Stephen Wolstenholme

unread,
Mar 26, 2013, 5:40:52 AM3/26/13
to
On Mon, 25 Mar 2013 21:52:43 +0100, "R.Wieser" <add...@not.available>
wrote:

>Stephen,
>
>Have you already checked what data you are feeding to that "isalnum"
>function (coming from the numeric keyboard) ?
>
>Most likely the problem is related to the method/function you are using to
>retrieve the data from the keyboard, not to the "isalnum" function.
>
>Regards,
>Rudy Wieser

I use CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);

R.Wieser

unread,
Mar 26, 2013, 7:31:09 AM3/26/13
to
Hello Stepehn,

> I use CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);

My apologies, but I do not really know vc.mfc all that well (my
language-of-choice is a different one). That means that although I can help
you by pointing out the most common causes of certain problems you have to
do the actual checking yourself.

So, did you look at what result that that "CScrollView::OnKeyDown" function
returns ? Does it return different results when pressing a normal and a
numeric "0" ?

Regards,
Rudy Wieser


-- Origional message:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
fiq2l8p6pldn8vj75...@4ax.com...

Stephen Wolstenholme

unread,
Mar 26, 2013, 7:53:05 AM3/26/13
to
On Tue, 26 Mar 2013 12:31:09 +0100, "R.Wieser" <add...@not.available>
wrote:

>So, did you look at what result that that "CScrollView::OnKeyDown" function
>returns ? Does it return different results when pressing a normal and a
>numeric "0" ?
>
>Regards,
>Rudy Wieser

It returns the correct character code for all keys. The code for
numeric keypad 0 is 96, 1 is 97, 2 is 98 etc. For some reason isalnum
does not include 96 so I have had to use
if(isalnum(nChar) || nChar == 96 || other keys

R.Wieser

unread,
Mar 26, 2013, 12:00:23 PM3/26/13
to
Stephen,

> It returns the correct character code for all keys. The
> code for numeric keypad 0 is 96, 1 is 97, 2 is 98 etc.

Actually, those are not near to "the correct character code" *at all* ...
:-\

The digit "0" is, in standard ASCII, equal to 48, going up to 57 for the
digit "9".

In standard ASCII 96 is a back-quote, 97 the "a", 98 the "b" and so on.

The problem is that your function returns *keycodes*, not characters.

Just try what happens when you type a normal character and than the same,
but now upper-case (shifted) one. For the second you will probably get two
codes, with the last one being equal to the non-shifted one (and the first
the keycode for the shift key).

In short: you're using the wrong command to retrieve your keyboard-data.

Regards,
Rudy Wieser


-- Origional message:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
e723l85ipo2sbb7bu...@4ax.com...

Stephen Wolstenholme

unread,
Mar 26, 2013, 1:07:39 PM3/26/13
to
On Tue, 26 Mar 2013 17:00:23 +0100, "R.Wieser" <add...@not.available>
wrote:

>Stephen,
>
>> It returns the correct character code for all keys. The
>> code for numeric keypad 0 is 96, 1 is 97, 2 is 98 etc.
>
>Actually, those are not near to "the correct character code" *at all* ...
>:-\
>
>The digit "0" is, in standard ASCII, equal to 48, going up to 57 for the
>digit "9".
>

Those are ASCII rather than VC++ keycodes.

>In standard ASCII 96 is a back-quote, 97 the "a", 98 the "b" and so on.
>

Again ASCII. The codes are not the same as ASCII.

>The problem is that your function returns *keycodes*, not characters.
>

To be accurate the function uses virtual keycodes in VC++. Virtual key
codes need to converted to characters using MapVirtualKey.

>Just try what happens when you type a normal character and than the same,
>but now upper-case (shifted) one. For the second you will probably get two
>codes, with the last one being equal to the non-shifted one (and the first
>the keycode for the shift key).
>
>In short: you're using the wrong command to retrieve your keyboard-data.

It the same code as I have used in lots of applications for many
years. We are at cross purposes aren't we! I'm talking VC++. It's
different to most other development software.

R.Wieser

unread,
Mar 26, 2013, 7:54:20 PM3/26/13
to
Stephen,

> Those are ASCII rather than VC++ keycodes.

Correct. Your "isalnum" function expects ASCII, not virtual keycodes.

Your "CScrollView::OnKeyDown" function on the other hand returns virtual
keycodes, not ASCII.

Both functions are simply not compatible with each other.

> Virtual key codes need to converted to characters using MapVirtualKey.

Thats one way to solve your problem, yes. Read keycode, *convert*, feed to
isalnum.

> It the same code as I have used in lots of applications
> for many years.

Than you now have lots of applications all with a major(?) bug in them. :-\

> We are at cross purposes aren't we!

I think you're right. I was trying to find where it went wrong and help
you fix it. What are you trying to do here ?

> I'm talking VC++. It's different to most other development
> software.

Not really. Besides, most programming languages have more similarities
than differences.

But hey, if you want to fight me because you can't handle you made a simple
mistake than I think I'm going to end our conversation here.

Regards,
Rudy Wieser

P.s.
Before you think of screaming your head off because, according to you, I do
not understand the first thing about programming or VC++, try feeding the
characters with ASCII codes 32 thru 126 (or even from 0 upto 255) to that
"isalnum" function of yours, and see if its results match the digits, upper-
and lower-case characters.

When you see it does you *could* come to the conclusion that that function
behaves as it should, and the problem lies elsewhere ...


-- Origional mesage:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
dqk3l8de5j2kja40i...@4ax.com...

Stephen Wolstenholme

unread,
Mar 27, 2013, 5:45:10 AM3/27/13
to
On Wed, 27 Mar 2013 00:54:20 +0100, "R.Wieser" <add...@not.available>
wrote:

>But hey, if you want to fight me because you can't handle you made a simple
>mistake than I think I'm going to end our conversation here.
>

I'm not fighting anyone. My original question was to find why it
happens rather than how to fix it. It has always been a simple fix but
it's still a mystery why numeric key 0 does not translate to an ASCII
while all other keys do.

R.Wieser

unread,
Mar 27, 2013, 3:51:03 PM3/27/13
to
Stephen,

> I'm not fighting anyone.

You could have fooled me.

> My original question was to find why it
> happens rather than how to fix it.

I have told you that. Several times:

DO NOT FEED KEYCODES INTO A FUNCTION THAT EXPECTS ASCII.

Thats like putting diesel into a car that expects petrol, and than throwing
your hands up because you have no clue that, although both are fuel, they
are quite different.

> ... but it's still a mystery why numeric key 0 does
> not translate to an ASCII while all other keys do.

Than you haven't been listening to anything I said I'm afraid.

Did you ever wonder why a square peg does not fit into a round hole ? I
mean, most of that square peg does actually fit in there, its just the
corners that are not accepted by that round hole. Yeah, surely its all the
fault of that round hole. :-)



Lets put it all thogether, shall we ?

1)You post a problem with a certain function, claiming it does not behave as
it should.

Whats the chance that this function, used by many programmers and inside
lots of programs, is actually malfunctioning and has stayed undetected all
this time ? I would say very little (a chance nearing Zero).

Logic conclusion: Its either your code or method that is flawed.

2) Alas, your post does not contain any code, which denies us the
possibility to determine and point-out the actual problem.

When asked for more detailed information all you can do is to name a single,
second command. Dude, really ?

3) When trying to point out the problem with the difference between those
two functions you come up with a lecture about, quote: "Virtual key codes
need to converted to characters using MapVirtualKey." without as much as a
single word to how that has any bearing on your problem. Not a single word
on if you used it in your code and if so how.

Am I supposed to (if you did actually use it) have just read that directly
from your mind ?

3) Although you have a problem with a command you're using and although you
claim to have created programs for many years you have not learned anything
about bug-hunting.

4) When someone else tries to help you (me) you are *activily opposing*
him -- probably because you simply do not believe that your own code could
be at fault.

Dude, you're the achtype noob: You want to learn, but only if what we tell
you matches what you think is the problem/cause. Everything else is simply
ignored. Thats worse than dumb I'm afraid.

Oh well, you can't say I didn't try, which is more than I can say from you.

Regards,
Rudy Wieser


-- Origional message.
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
fjf5l81o76mi0oqq7...@4ax.com...

Stephen Wolstenholme

unread,
Mar 28, 2013, 5:44:26 AM3/28/13
to
On Wed, 27 Mar 2013 20:51:03 +0100, "R.Wieser" <add...@not.available>
wrote:

>2) Alas, your post does not contain any code, which denies us the
>possibility to determine and point-out the actual problem.

I did not to post the code but here it is:-

void CEasyNNView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(theApp.m_nTraceLevel > 0)
theApp.Trace(_T("OnKeyDown"));

CEasyNNDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

CDiagnostics dlgDiagnostics;

COrder dlgOrder;

int nResult = NOT_EDITED;

int nFound;

SHORT nLShift = 0;

SHORT nRShift = 0;

SHORT nControl = 0;

// Stop first click move
theApp.m_bInit = FALSE;

UINT nScroll;

CString strChar, strTemp;

CString strDefaults, strNames;

CFileStatus fileStatus;

BYTE byteKeyboardState[256];

switch(nChar)
{
case VK_HOME:

if(pDoc->m_bViewGrid)
{
if(m_bLastVert)
{
OnVScroll(SB_TOP, 0, GetScrollBarCtrl(SB_VERT));

GoTo(0, m_nCellCol);
}
else
{
OnHScroll(SB_LEFT, 0, GetScrollBarCtrl(SB_HORZ));

GoTo(m_nCellRow, 0);
}
}

if(pDoc->m_bViewGraphColumn || pDoc->m_bViewSensitivity)
{
m_nCellCol = 0;

pDoc->Refresh();

Invalidate();
}

if(pDoc->m_bViewAssociations)
OnVScroll(SB_TOP, 0, GetScrollBarCtrl(SB_VERT));

break;

case VK_END:

if(pDoc->m_bViewGrid)
{
if(m_bLastVert)
{
OnVScroll(SB_BOTTOM, 0, GetScrollBarCtrl(SB_VERT));

GoTo(pDoc->m_nRows - 1, m_nCellCol);
}
else
{
OnHScroll(SB_RIGHT, 0, GetScrollBarCtrl(SB_HORZ));

GoTo(m_nCellRow, pDoc->m_nCols - 1);
}
}

if(pDoc->m_bViewGraphColumn || pDoc->m_bViewSensitivity)
{
m_nCellCol = pDoc->m_nCols - 1;

pDoc->Refresh();

Invalidate();
}

if(pDoc->m_bViewAssociations)
OnVScroll(SB_BOTTOM, 0, GetScrollBarCtrl(SB_VERT));

break;

case VK_PRIOR:

OnVScroll(SB_PAGEUP, 0, GetScrollBarCtrl(SB_VERT));

m_bLastVert = TRUE;

break;

case VK_NEXT:

OnVScroll(SB_PAGEDOWN, 0, GetScrollBarCtrl(SB_VERT));

m_bLastVert = TRUE;

break;

case VK_DOWN:

if(pDoc->m_bViewGrid || pDoc->m_bViewGraphColumn)
{
if(m_nCellRow < pDoc->m_nRows)
{
m_nCellRow++;

if(CellTooLow() && pDoc->m_bViewGrid)
{
nScroll = GetVScrollInfo(POS);
SetVScrollInfo(POS, nScroll + m_nRowHeight);
m_nScrollRows++;
Invalidate();
}
}
}
else
OnVScroll(SB_LINEDOWN, 0, GetScrollBarCtrl(SB_VERT));

m_bLastVert = TRUE;

break;

case VK_UP:

if(pDoc->m_bViewGrid || pDoc->m_bViewGraphColumn)
{
if(m_nCellRow > 0)
{
m_nCellRow--;

if(CellTooHigh() && pDoc->m_bViewGrid)
{
nScroll = GetVScrollInfo(POS);
SetVScrollInfo(POS, nScroll - m_nRowHeight);
m_nScrollRows--;
Invalidate();
}
}
}
else
OnVScroll(SB_LINEUP, 0, GetScrollBarCtrl(SB_VERT));

m_bLastVert = TRUE;

break;

case VK_RIGHT:

case VK_TAB:

if(pDoc->m_bViewGrid)
{
if(m_nCellCol < pDoc->m_nCols)
{
m_nCellCol++;

if(CellTooRight())
{
nScroll = GetHScrollInfo(POS);
SetHScrollInfo(POS, nScroll + m_nColWidth);
m_nScrollCols++;
Invalidate();
}
}
}
else if(pDoc->m_bViewGraphColumn || pDoc->m_bViewSensitivity)
{
if(m_nCellCol < pDoc->m_nCols - 1)
m_nCellCol++;

if(m_nCellCol > pDoc->m_nCols - 1)
m_nCellCol = pDoc->m_nCols - 1;

if(pDoc->m_bViewSensitivity)
{
CInOut* pInOut = NULL;

pInOut = pDoc->GetInOut(m_nCellCol);

while(pInOut->m_nInOutType != IN_OUT_OUTPUT)
{
m_nCellCol++;

if(m_nCellCol > pDoc->m_nCols - 1)
{
m_nCellCol = pDoc->m_nCols - 1;

break;
}

pInOut = pDoc->GetInOut(m_nCellCol);
}
}

pDoc->Refresh();

Invalidate();
}
else
OnHScroll(SB_LINERIGHT, 0, GetScrollBarCtrl(SB_HORZ));

m_bLastVert = FALSE;

break;

case VK_LEFT:

case VK_BACK:

if(pDoc->m_bViewGrid)
{
if(m_nCellCol > 0)
{
m_nCellCol--;

if(CellTooLeft())
{
nScroll = GetHScrollInfo(POS);
SetHScrollInfo(POS, nScroll - m_nColWidth);
m_nScrollCols--;
Invalidate();
}
}
}
else if(pDoc->m_bViewGraphColumn || pDoc->m_bViewSensitivity)
{
if(m_nCellCol > 0)
m_nCellCol--;

if(m_nCellCol < 0)
m_nCellCol = 0;

if(pDoc->m_bViewSensitivity)
{
CInOut* pInOut = NULL;

pInOut = pDoc->GetInOut(m_nCellCol);

while(pInOut->m_nInOutType != IN_OUT_OUTPUT)
{
m_nCellCol--;

if(m_nCellCol < 0)
{
m_nCellCol = 0;

break;
}

pInOut = pDoc->GetInOut(m_nCellCol);
}
}

pDoc->Refresh();

Invalidate();
}
else
OnHScroll(SB_LINELEFT, 0, GetScrollBarCtrl(SB_HORZ));

m_bLastVert = FALSE;

break;

case VK_ESCAPE:

if(pDoc->m_bViewGrid)
{
pDoc->m_nSelectedCol = NONE;

pDoc->m_nSelectedRow = NONE;

Invalidate();
}

break;

case VK_F7:

if(pDoc->m_bIsLearning)
break;

if(theApp.m_bTrace)
{
theApp.m_bTrace = FALSE;

AfxMessageBox(_T("Tracing has been switched off"));

break;
}

dlgDiagnostics.m_nWarnLevel = 0;

dlgDiagnostics.m_nTraceLevel = theApp.m_nTraceLevel;

dlgDiagnostics.m_strEditTraceKeyword =
theApp.m_strTraceKeyword;

if(dlgDiagnostics.DoModal() == IDOK)
{
theApp.m_nWarnLevel = dlgDiagnostics.m_nWarnLevel;

theApp.m_nTraceLevel = dlgDiagnostics.m_nTraceLevel;

theApp.m_strTraceKeyword =
dlgDiagnostics.m_strEditTraceKeyword;

theApp.m_nTraceCount = 0;

theApp.m_nTraceRepeats = 0;

theApp.m_nTraceCycles = 0;

theApp.m_strLastTrace.Empty();

if(theApp.m_nTraceLevel > 0)
{
CFile file;

CFileException fileException;

theApp.m_strTraceName = _T("enntrace.txt");

CFileDialog dlgFile(FALSE, _T("txt"),
theApp.m_strTraceName, NULL, NULL);

// Create new trace file
dlgFile.m_ofn.lpstrTitle = _T("Open trace file");

if(dlgFile.DoModal() == IDOK)
{
theApp.m_strTraceName = dlgFile.GetPathName();

if(!file.Open(theApp.m_strTraceName,
CFile::modeCreate | CFile::modeNoTruncate, &fileException))
{
// Try again
if(!file.Open(theApp.m_strTraceName,
CFile::modeCreate | CFile::modeNoTruncate, &fileException))
{
theApp.m_bTrace = FALSE;

return;
}
}

file.Close();

theApp.m_bTrace = TRUE;
}
}
}

break;

case VK_F8:

if(pDoc->m_bIsLearning)
break;

strDefaults = theApp.GetProfileString(_T("Tips1"),
_T("OpenDefaults"), NULL);

theApp.m_nDisplayBool++;

if(theApp.IsDefault(ID_DEFAULTS_OPEN))
{
strTemp = _T("Bool Names = ");

nFound = strDefaults.Find(strTemp);

if(nFound > 0)
{
strTemp = strDefaults.Mid(nFound, strTemp.GetLength()
+ 2);

strNames.Format(_T("Bool Names = %d"),
theApp.m_nDisplayBool);

strDefaults.Replace(strTemp, strNames);

theApp.WriteProfileString(_T("Tips1"),
_T("OpenDefaults"), strDefaults);
}
}

Invalidate();

pDoc->SetModifiedFlag();

break;

case VK_F9:

if(pDoc->m_bIsLearning)
break;

theApp.m_nDisplayNumbers++;

if(theApp.m_nDisplayNumbers > 2)
theApp.m_nDisplayNumbers = 0;

pDoc->SetModifiedFlag();

break;

#ifdef TRIAL

case VK_F4:
case VK_F3:
case VK_F2:

if(pDoc->m_bIsLearning)
break;

dlgOrder.DoModal();

break;

#endif

default:

if(pDoc->m_bViewGrid)
{
theApp.m_bMove = FALSE;

theApp.m_bReturn = FALSE;

nLShift = GetAsyncKeyState(VK_LSHIFT);

nRShift = GetAsyncKeyState(VK_RSHIFT);

GetKeyboardState(byteKeyboardState);

if(theApp.m_bUndo)
pDoc->EnableCheckPoint();
else
pDoc->DisableCheckPoint();

if(theApp.m_bDemoRunning)
{
nControl = GetAsyncKeyState(VK_CONTROL);

if(nControl & 0x8000)
break;
}

if(isalnum(nChar) || nChar == 96 /* Num pad 0 */ || nChar
== 187 || nChar == 188 || nChar == 189 || nChar == 190 || nChar ==
191)
{
GoTo(m_nCellRow, m_nCellCol);

nChar = MapVirtualKey(nChar, 2);

nChar = tolower(nChar);

if(byteKeyboardState[VK_CAPITAL] || (nLShift & 0x8000)
|| (nRShift & 0x8000))
nChar = toupper(nChar);

nResult = EditGrid(nChar);

theApp.m_bMove = TRUE;
}

if(nChar == VK_RETURN || nChar == VK_SPACE)
{
GoTo(m_nCellRow, m_nCellCol);

// Must do before EditGrid
theApp.m_bReturn = TRUE;

nResult = EditGrid();
}

switch(nResult)
{
case NO_CELL:

pDoc->AddRow();

pDoc->AddCol(TRUE, FALSE, TRUE);

break;

case NO_ROW:

if(theApp.m_bPresets)
Insert(EXAMPLE_TRAINING, INSERT_ALL,
pDoc->m_nRows);
else
pDoc->AddRow();

break;

case NO_COL:

pDoc->AddCol(TRUE, FALSE, TRUE);

break;
}

if(nResult != NOT_EDITED)
{
Invalidate();

NextCell();

if(CellTooHigh())
{
nScroll = GetVScrollInfo(POS);
SetVScrollInfo(POS, nScroll - m_nRowHeight);
m_nScrollRows--;
Invalidate();
}
else if(CellTooLeft())
{
nScroll = GetHScrollInfo(POS);
SetHScrollInfo(POS, nScroll - m_nColWidth);
m_nScrollCols--;
Invalidate();
}
else if(CellTooRight())
{
nScroll = GetHScrollInfo(POS);
SetHScrollInfo(POS, nScroll + m_nColWidth);
m_nScrollCols++;
Invalidate();
}
else if(CellTooLow())
{
nScroll = GetVScrollInfo(POS);
SetVScrollInfo(POS, nScroll + m_nRowHeight);
m_nScrollRows++;
Invalidate();
}
}
}
}

theApp.m_bMark = FALSE;

MarkGridCell();

AlignVerticalScroll();

::PostMessage(AfxGetMainWnd()->m_hWnd, WM_APP_POSITION,
m_nCellRow, m_nCellCol);

if(!pDoc->m_bViewGrid)
m_bLastVert = TRUE;

CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);

R.Wieser

unread,
Mar 28, 2013, 9:09:57 AM3/28/13
to
Stephen,

You appear to, just as you said and I understood, stuff the "nChar" virtual
keycode output of "CEasyNNView::OnKeyDown" straight into that "isalnum"
function, without any translation from virtual keycode to character.

As such I have no idea why you posted

"Virtual key codes need to converted to characters using MapVirtualKey"

without actually doing it.

Last suggestion (which you will probably also ignore, but you can't say
nobody tried to tell you) : Find yourself a list of virtual keycodes and
one with the ASCII codes. But them next to each other. You will see that
although there is some overlap (mostly letters and digits), some of the
symbols, like the numeric 1 thru 9 virtual keycodes, are not matched with
the same ones in the ASCII list.

Now if you press the button with the virtual keycode 106, being the numeric
multiply (*) symbol, you will see that it also is regarded as an
alphanumeric symbol. So will the F1 thru F11 (not the F12) keys.

Heck, even simpler : display the virtual keycode output of your
"CEasyNNView::OnKeyDown" function in a textbox (both the value and the
character please) and see what Windows itself thinks that they represent.

If you do you will notice that you will only get uppercase characters back,
no lowercase. Your numeric keys will also return something, but not what you
typed.
Also notice that all the control keys (both shifts, ctrls, alts and others)
return "characters"

If this doesn't convince to the difference of virtual keys and (ASCII)
characters you than I do not know what, if anything, will ...

Regards,
Rudy Wieser


-- Origional message:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
os38l81v27vk6me85...@4ax.com...

Stephen Wolstenholme

unread,
Mar 28, 2013, 9:44:26 AM3/28/13
to
On Thu, 28 Mar 2013 14:09:57 +0100, "R.Wieser" <add...@not.available>
wrote:

>As such I have no idea why you posted
>
>"Virtual key codes need to converted to characters using MapVirtualKey"
>
>without actually doing it.

I do call it but only if the key code is alpha numeric as the virtual
key is equal to the character code for alpha numeric characters. It
works just as well as calling MapVirtualKey before isalnum but saves a
call.

Steve

Geoff

unread,
Mar 29, 2013, 3:33:59 AM3/29/13
to
On Thu, 28 Mar 2013 13:44:26 +0000, Stephen Wolstenholme
<st...@npsl1.com> wrote:

>I do call it but only if the key code is alpha numeric as the virtual
>key is equal to the character code for alpha numeric characters. It
>works just as well as calling MapVirtualKey before isalnum but saves a
>call.

Why are you trying to save a call? Why not call MapVirtualKey in every
case and be done with all the issues. It seems to me your method is a
premature optimization.

Your big test, if(isalnum(nChar) || nChar == 96 /* Num pad 0 */ ||
nChar == 187 || nChar == 188 || nChar == 189 || nChar == 190 || nChar
== 191) is full of magic numbers and probably wastes more CPU cycles
and it is definitely harder to maintain than simply calling
MapVirtualKey unconditionally.

FYI, the zero key is ASCII zero, 0x30. The numeric pad zero key is
VK_NUMPAD0 or 0x60 as you have it in your conditional but it will fail
the isalnum since it's the ` key on the qwerty keyboard.

http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx

Use MapVirtualKey, then you won't have to worry about what you are
feeding isalnum().

Stephen Wolstenholme

unread,
Mar 29, 2013, 6:23:04 AM3/29/13
to
On Fri, 29 Mar 2013 00:33:59 -0700, Geoff <ge...@invalid.invalid>
wrote:
I wrote that code about ten years ago and I can't remember why I wrote
it that way but I'm sure I had a good reason at the time. The only
reason I can see now is to avoid five calls. I was looking at the code
was because one of my users pointed out numeric pad with num lock key
0 didn't work. I still don't know why!

R.Wieser

unread,
Mar 29, 2013, 7:53:31 AM3/29/13
to
Stephen,

> I do call it but only if the key code is alpha numeric as
> the virtual key is equal to the character code for alpha
> numeric characters.

And now you know that that isn't always true.

Worse, the reason why it *seemed* to be true is that, by pure luck, those
most of those virtual keycodes for the numeric keyboard fell into a range of
lower-case letters in the ASCII table.

So, either use that MapVirtualKey every time to convert the virtual key to
an ASCII symbol before feeding it to the isalnum function, or do not use
that function at all but create a comparision to filter the three ranges of
virtual keycodes (letters, normal digits, numeric keyboard digits) yourself.

I would suggest to listen to Geoff in this respect though: comparing with
"magic numbers" will often bite you in the behind in the long run.

Regards,
Rudy Wieser


-- Origional message:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
kdh8l8t83f41vr428...@4ax.com...

R.Wieser

unread,
Mar 29, 2013, 7:57:37 AM3/29/13
to
Stephen,

> I was looking at the code was because one of my users
> pointed out numeric pad with num lock key 0 didn't work.
> I still don't know why!

Major facepalm.

So much explanation, from me as well as from Geof, and you still have no
idea ? It boggles the mind.

Regards,
Rudy Wieser

-- Origional message:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
i1qal8tasekh2a6fi...@4ax.com...

Stephen Wolstenholme

unread,
Mar 29, 2013, 8:18:46 AM3/29/13
to
On Fri, 29 Mar 2013 12:53:31 +0100, "R.Wieser" <add...@not.available>
wrote:

>I would suggest to listen to Geoff in this respect though: comparing with
>"magic numbers" will often bite you in the behind in the long run.

The "magic numbers" are arithmetic functions. I have now changed the
code to call MapVirtualKey first. No doubt I will now find out why I
did it later in the thread!

R.Wieser

unread,
Mar 29, 2013, 9:52:17 AM3/29/13
to
Stephen,

> The "magic numbers" are arithmetic functions.

Another misconception I'm afraid. Numbers != arithmetic functions.

The "magic numbers" I referred to where the VK_* values you compare the
results of that KeyDown with. Like VK_NUMPAD0 for the virtual keycode of
the numeric "0"

Regards,
Rudy Wieser

Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
f71bl813v4emvi8t8...@4ax.com...

Stephen Wolstenholme

unread,
Mar 29, 2013, 10:26:38 AM3/29/13
to
On Fri, 29 Mar 2013 14:52:17 +0100, "R.Wieser" <add...@not.available>
wrote:

>Stephen,
>
>> The "magic numbers" are arithmetic functions.
>
>Another misconception I'm afraid. Numbers != arithmetic functions.
>
>The "magic numbers" I referred to where the VK_* values you compare the
>results of that KeyDown with. Like VK_NUMPAD0 for the virtual keycode of
>the numeric "0"
>
>Regards,
>Rudy Wieser

I don't remember you referring to "magic numbers". I took the "magic
numbers" referred to by Geoff as the 187, 188, 189, 190, 191 in my
code representing the arithmetic +,-.*/ They are in the code so that
the editor can include simple arithmetic term. For example if a user
wants enter 2.7272727 they could use 30/11

R.Wieser

unread,
Mar 29, 2013, 11:44:26 PM3/29/13
to
Stephen,

> I don't remember you referring to "magic numbers".

Correct. I have to confess that I do have a bad habit: I also read other
peoples replies to a thread I'm involved in. Its allways possible they know
something I do not (yet) know. Next to that it helps me not to say exactly
the same as someone else already has.

> I took the "magic numbers" referred to by Geoff as
> the 187, 188, 189, 190, 191

I'm sorry, but thats not what you said.

But yes, those numbers *are* "magic". *All* of them. Because you have found
them to work and *for that reason only* are using them. Without
understanding. Isn't that the definition of "working by magic" ?

But it gets even worse than that: The numbers you mentioned here are
specified in the Virtual Keycode list as being OEM (original equipment
manufacturers) codes, meaning that every company creating keyboards can
use/assign them as they see fit.

Such numbers which have only a meaning within the context of a specific
manufacturer are often referred to as "magic numbers".

> They are in the code so that the editor can include simple
> arithmetic term. For example if a user wants enter 2.7272727
> they could use 30/11

I understand. But take Geofs advice, first convert and than compare. The
result will be a much more maintainable and stable program.

Even if you would ignore the rather important "working exactly as intended"
/"working without side effects" (I think I already mentioned that, among
others, F1 thru F11 will cause strange effects. By the way: have you tried
that yet ? Why not ? )

You mentioned something in the line of not wanting to waste time on that
conversion ? Do you realize that most of the time the computer is just
*waiting for you* to press a key ? That the extra time needed for
conversion is a negligible fraction of that ?

Regards,
Rudy Wieser


-- Origional message:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
pv7bl8d5aib5g2cs5...@4ax.com...

Geoff

unread,
Mar 30, 2013, 12:00:27 AM3/30/13
to
On Fri, 29 Mar 2013 14:26:38 +0000, Stephen Wolstenholme
<st...@npsl1.com> wrote:

>On Fri, 29 Mar 2013 14:52:17 +0100, "R.Wieser" <add...@not.available>
>wrote:
>
>>Stephen,
>>
>>> The "magic numbers" are arithmetic functions.
>>
>>Another misconception I'm afraid. Numbers != arithmetic functions.
>>
>>The "magic numbers" I referred to where the VK_* values you compare the
>>results of that KeyDown with. Like VK_NUMPAD0 for the virtual keycode of
>>the numeric "0"
>>
>>Regards,
>>Rudy Wieser
>
>I don't remember you referring to "magic numbers". I took the "magic
>numbers" referred to by Geoff as the 187, 188, 189, 190, 191 in my
>code representing the arithmetic +,-.*/ They are in the code so that
>the editor can include simple arithmetic term. For example if a user
>wants enter 2.7272727 they could use 30/11
>
>Steve

Yes, those are the magic numbers to which I was referring.

Those are the ASCII values of those characters you are trying to
filter but the virtual key codes for the numeric key pad VK_MULTIPLY
0x6A, VK_ADD 0x6B, VK_SUBTRACT 0x6D, VK_DIVIDE 0x6F are what you
should have been using from the start instead of numeric constants.

The numeric pad keys of those values, 187 to191 are:
VK_OEM_PLUS 0xBB, VK_OEM_COMMA 0xBC, VK_OEM_MINUS 0xBD, VK_OEM_PERIOD
0xBE, VK_OEM_2 0xBF, Used for miscellaneous characters; it can vary by
keyboard. For the US standard keyboard, the '/?' key

Had you been using the VK_* macros instead of magic numbers your code
would be self documenting and you would have been aware of the latent
bug in your program due to the fact you are passing VK codes to
isalnum() and not ASCII characters.

I have no doubt you will uncover some more bugs since nChar is very
problematic in the code you presented. In one case it's being
interpreted as ASCII, in another it's a VK code. I know what it's like
looking at code you wrote years ago. Perhaps with new eyes you can see
a better solution now.

I was going to mention the Win32 API function IsCharAlphaNumeric but I
think it won't work any better than isalum() other than it is aware of
the Windows keyboard locale and not stuck in the C locale like the
runtime. This may or may not matter to you depending on if you have
users in non-English/US locales.

Geoff

unread,
Mar 30, 2013, 12:31:21 AM3/30/13
to
On Thu, 28 Mar 2013 09:44:26 +0000, Stephen Wolstenholme
<st...@npsl1.com> wrote:

>if(isalnum(nChar) || nChar == 96 /* Num pad 0 */ || nChar
>== 187 || nChar == 188 || nChar == 189 || nChar == 190 || nChar ==
>191)

I suppose you could write this as

if(isalnum(MapVirtualKey(nChar, 2)) || nChar == 187 || nChar == 188 ||
nChar == 189 || nChar == 190 || nChar == 191)

without affecting the rest of your function but I still think you can
find a better solution.

Geoff

unread,
Mar 30, 2013, 2:05:55 AM3/30/13
to
It took some time to fathom what you were trying to do but I think
this will work for you:

if(IsCharAlphaNumeric(MapVirtualKey(nChar, 2)) ||
nChar == VK_ADD ||
nChar == VK_SUBTRACT ||
nChar == VK_MULTIPLY ||
nChar == VK_DIVIDE ||
nChar == VK_DECIMAL)

At this point I don't know if you left VK_COMMA out of this filter
deliberately or by mistake since it was 188 in your code but you
didn't capture multiply in your magic numbers. I can only see that
your function would have failed for numpad keys / * - + . anyway.

I also would advise using CharLower and CharUpper for converting your
strings in place.

Stephen Wolstenholme

unread,
Mar 30, 2013, 5:54:46 AM3/30/13
to
On Sat, 30 Mar 2013 04:44:26 +0100, "R.Wieser" <add...@not.available>
wrote:

>Stephen,
>
The changes suggested by you and Geoff are included in the next
update.

F1 to F10 work as expected. The program does not use F11 in release
mode.

The time wasting I mentioned is related to a calculating thread
priority problem. One of the threads has to wait for all grid array
changes which may be new data being entered. This is also sorted out
in the next update.

Stephen Wolstenholme

unread,
Mar 30, 2013, 6:02:13 AM3/30/13
to
Thanks for the help Geoff. I am including all suggested changes in the
next update. I'm beginning to wonder why only one bug has been found
in the current release. It was beta tested by 200 users! The '0'
problem was the only bug reported.

R.Wieser

unread,
Mar 30, 2013, 11:12:31 AM3/30/13
to
Stephen.

> F1 to F10 work as expected.

Odd, as they should pass the "isalnum" test without a problem (check the
virtual keyodes for those keys, and what they are recognised as when
regarded as ASCII symbols). I guess that maybe the Virtual keymapping later
on filters them out.

I guess *some* things should go your way. :-)

Regards,
Rudy Wieser


-- Origional message:
Stephen Wolstenholme <st...@npsl1.com> schreef in berichtnieuws
n1ddl8pt2hd1oltm2...@4ax.com...

Stephen Wolstenholme

unread,
Mar 30, 2013, 12:34:10 PM3/30/13
to
On Sat, 30 Mar 2013 16:12:31 +0100, "R.Wieser" <add...@not.available>
wrote:

>Stephen.
>
>> F1 to F10 work as expected.
>
>Odd, as they should pass the "isalnum" test without a problem (check the
>virtual keyodes for those keys, and what they are recognised as when
>regarded as ASCII symbols). I guess that maybe the Virtual keymapping later
>on filters them out.
>
>I guess *some* things should go your way. :-)
>
>Regards,
>Rudy Wieser

Rudy,

VK_F1 to VK_F10 are accelerator resources as below and are handled
before the call to isalnum

Steve

IDR_MAINFRAME ACCELERATORS
BEGIN
"J", ID_ACTION_JOG, VIRTKEY, CONTROL, NOINVERT
VK_RETURN, ID_ACTION_REFRESH, VIRTKEY, CONTROL, NOINVERT
VK_SPACE, ID_ACTION_START_LEARNING, VIRTKEY, SHIFT, NOINVERT
VK_SPACE, ID_ACTION_STOP, VIRTKEY, CONTROL, NOINVERT
VK_F10, ID_CREDITS, VIRTKEY, CONTROL, ALT,
NOINVERT
"D", ID_DUMP, VIRTKEY, CONTROL, ALT,
NOINVERT
"Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT
"Y", ID_EDIT_REDO, VIRTKEY, CONTROL, NOINVERT
"C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
"X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
VK_DELETE, ID_EDIT_DELETE, VIRTKEY, NOINVERT
"F", ID_EDIT_FIND, VIRTKEY, CONTROL, NOINVERT
"A", ID_EDIT_FIND_AGAIN, VIRTKEY, CONTROL, NOINVERT
VK_F3, ID_EDIT_FIND_AGAIN, VIRTKEY, NOINVERT
"G", ID_EDIT_GO_TO, VIRTKEY, CONTROL, NOINVERT
"T", ID_EDIT_GO_TO_AGAIN, VIRTKEY, CONTROL, NOINVERT
VK_F4, ID_EDIT_GO_TO_AGAIN, VIRTKEY, NOINVERT
"U", ID_EDIT_GO_TO_USED, VIRTKEY, CONTROL, NOINVERT
VK_F2, ID_EDIT_GO_TO_USED, VIRTKEY, NOINVERT
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT
"H", ID_EDIT_REPLACE_VALUES, VIRTKEY, CONTROL, NOINVERT
"N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
"O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
"P", ID_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT
"S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
VK_F1, ID_HELP_CHM, VIRTKEY, NOINVERT
VK_F4, ID_MACRO_PLAY, VIRTKEY, CONTROL, NOINVERT
VK_F2, ID_MACRO_RECORD, VIRTKEY, CONTROL, NOINVERT
VK_F3, ID_MACRO_STOP, VIRTKEY, CONTROL, NOINVERT
VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT
VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT
VK_F5, ID_REGISTER, VIRTKEY, CONTROL, NOINVERT
"Q", ID_VOLUME_DECREASE, VIRTKEY, CONTROL, NOINVERT
"W", ID_VOLUME_INCREASE, VIRTKEY, CONTROL, NOINVERT
END

Geoff

unread,
Mar 30, 2013, 8:02:48 PM3/30/13
to
On Sat, 30 Mar 2013 10:02:13 +0000, Stephen Wolstenholme
<st...@npsl1.com> wrote:

>Thanks for the help Geoff. I am including all suggested changes in the
>next update. I'm beginning to wonder why only one bug has been found
>in the current release. It was beta tested by 200 users! The '0'
>problem was the only bug reported.
>
>Steve

You're doing pretty good with only 1 bug reported in beta. :)

It sounds like your numpad users are in the minority. I know I never
got into the habit of using it. I only use it occasionally and seldom
for spreadsheets, I don't know why. I'm left handed so that might have
something to do with it.

Advisory: don't use CharLower and CharUpper on your nChar, wrong
variable type and nChar isn't a string and those functions require the
character/string be a valid (zero terminated) C string.

Stephen Wolstenholme

unread,
Apr 1, 2013, 5:55:01 AM4/1/13
to
On Sat, 30 Mar 2013 17:02:48 -0700, Geoff <ge...@invalid.invalid>
wrote:

>On Sat, 30 Mar 2013 10:02:13 +0000, Stephen Wolstenholme
><st...@npsl1.com> wrote:
>
>>Thanks for the help Geoff. I am including all suggested changes in the
>>next update. I'm beginning to wonder why only one bug has been found
>>in the current release. It was beta tested by 200 users! The '0'
>>problem was the only bug reported.
>>
>>Steve
>
>You're doing pretty good with only 1 bug reported in beta. :)
>
>It sounds like your numpad users are in the minority. I know I never
>got into the habit of using it. I only use it occasionally and seldom
>for spreadsheets, I don't know why. I'm left handed so that might have
>something to do with it.

I'm left handed as well and never use the numpad. It seems that most
right handed people don't use it either.

>
>Advisory: don't use CharLower and CharUpper on your nChar, wrong
>variable type and nChar isn't a string and those functions require the
>character/string be a valid (zero terminated) C string.

I don't use either.

Thanks

Geoff

unread,
Apr 1, 2013, 1:52:01 PM4/1/13
to
On Mon, 01 Apr 2013 10:55:01 +0100, Stephen Wolstenholme
<st...@npsl1.com> wrote:

>I'm left handed as well and never use the numpad. It seems that most
>right handed people don't use it either.

I pretty much have my right hand on the mouse unless I am typing, then
both hands are on the qwerty keys, touch typing in the way I learned
back in HS. I am not a great touch typist but I manage.

I have a right handed friend who uses the numpad for all numeric
entries.

I have a left handed friend who uses his mouse left handed and
mirrored.

They both drive me nuts. :)
0 new messages