The problem is that the app doesn't recognise SHIFT t (i.e) CAPITAL T.
Strangely enough when I try to type a capital T in my mfc app nothing happens. If I use Caps Lock it works, but Shift t doesn't work. Initially I thought my keyboard had become faulty, but when I discovered that Shift t works in every other app in my system I started to wonder why.
I try to debug the app, by to find the error, debugging shows that my app's view class/object doesnt receive any OnChar (WM_CHAR) message when shift t keys are depressed. Isn't this the greatest wonder in the world. Please what can be the cause and what can be the solution. In case you are wondering, my app responds to every other characters and character combination?
Okay here are useful information about the app.
1. My document object has (among others) a private data member : TableFigure *m_pEditTableBox ( acceesible by calling : TableFigure * GetEditTable();
2. TableFigure m_pEditTableBox, has (among others),a private data member: Table *m_pTable (accessible by calling: void Table *GetTable();
3.Table *m_pTable has (among others) a data member: TCell *m_ptcell (accessible by calling
TCell *GetEditCell();
4. TCell *m_ptcell has among others, a data member: TableTextFigure *m_pEditText ( accessible by calling TableTextFigure *GetEditTableText();
5. TableTextFigure inherits TextFigure;
#pragma once
#include "..\\Caret.h"
#include "..\\Color.h"
#include "..\\MyFont.h"
#include "Figure.h"
typedef CArray<int> IntArray;
enum KeyboardState {KS_INSERT, KS_OVERWRITE};
enum TextDirection {LEFT_TO_RIGHT,TOP_TO_BOTTOM,BOTTOM_TO_TOP};
enum TextAlignment {TOP_LEFT,TOP_CENTRE,TOP_RIGHT,MIDDLE_LEFT,MIDDLE_CENTRE,MIDDLE_RIGHT,BOTTOM_LEFT,BOTTOM_CENTRE,BOTTOM_RIGHT};
class TextFigure: public Figure
{
public:
TextFigure();
TextFigure(const Color& color, const CPoint& ptMouse,
const MyFont& font, CDC* pDC);
TextFigure(const TextFigure& text);
Figure* Copy() const;
void Serialize(CArchive& archive);
BOOL Click(const CPoint& ptMouse);
BOOL DoubleClick(const CPoint& ptMouse);
BOOL Inside(const CRect& rcInside) const;
void MoveOrModify(const CSize& szDistance);
void Move(const CSize& szDistance);
virtual BOOL KeyDown(UINT uChar, CDC* pDC);
virtual void CharDown(UINT uChar, CDC* pDC,KeyboardState eKeyboardState);
void SetPreviousText(CDC* pDC);
void Draw(CDC* pDC) const;
CRect GetArea() const;
BOOL PointInFigure(const CPoint &ptMouse) const;
MyFont* GetFont() {return &m_font;}
virtual void SetFont(const MyFont& font, CDC* pDC);
int GetTextLength() { return m_stText.GetLength();}
CString GetText() { return m_stText;}
CString *GetActualText() { return &m_stText;}
void SetText(CString stText){ m_stText = stText;}
int *GetEditIndex() { return &m_iEditIndex;}
void UpdateCaretArray(CDC *pDC) {GenerateCaretArray(pDC);}
CPoint GetTextPoint() { return m_ptText;}
CPoint *GetMyTextPoint() { return &m_ptText;}
CPoint GetTextInfo(TEXTMETRIC *ptm);
void MouseDown(const CPoint& ptMouse);
BOOL PointInText(const CPoint &ptMouse);
void SetTextDirection(TextDirection eDirection){ m_eTextDirection = eDirection;}
TextDirection GetTextDirection() { return m_eTextDirection;}
void SetTextAlignment(TextAlignment eAlignment){ m_eTextAlignment = eAlignment;}
TextAlignment GetTextAlignment() { return m_eTextAlignment;}
protected:
void GenerateCaretArray(CDC* pDC);
public:
CRect GetCaretArea(KeyboardState eKeyboardState);
HCURSOR GetCursor() const;
private:
enum {CREATE_TEXT, MOVE_TEXT, EDIT_TEXT, NONE_TEXT} m_eDragMode;
protected:
CPoint m_ptText;
CSize m_szText;
CString m_stText, m_stPreviousText;
int m_iAverageWidth;
MyFont m_font;
int m_iEditIndex;
IntArray m_caretArray;
TextDirection m_eTextDirection;
TextAlignment m_eTextAlignment;
};
Relevant Textfigure codes are:
BOOL TextFigure::KeyDown(UINT uChar, CDC* pDC)
{
int iLength = m_stText.GetLength();
switch (uChar)
{
case VK_HOME:
if (m_iEditIndex > 0)
{
m_iEditIndex = 0;
}
break;
case VK_END:
if (m_iEditIndex < iLength)
{
m_iEditIndex = iLength;
}
break;
case VK_LEFT:
if (m_iEditIndex > 0)
{
--m_iEditIndex;
}
break;
case VK_RIGHT:
if (m_iEditIndex < m_stText.GetLength())
{
++m_iEditIndex;
}
break;
case VK_DELETE:
if (m_iEditIndex < m_stText.GetLength())
{
m_stText.Delete(m_iEditIndex);
GenerateCaretArray(pDC);
return TRUE;
}
break;
case VK_BACK:
if (m_iEditIndex > 0)
{
--m_iEditIndex;
m_stText.Delete(m_iEditIndex);
GenerateCaretArray(pDC);
return TRUE;
}
break;
}
return FALSE;
}
void TextFigure::CharDown(UINT uChar, CDC* pDC, KeyboardState eKeyboardState)
{
if (m_iEditIndex == m_stText.GetLength())
{
m_stText.AppendChar((TCHAR) uChar);
}
else
{
switch (eKeyboardState)
{
case KS_INSERT:
m_stText.Insert(m_iEditIndex, (TCHAR) uChar);
break;
case KS_OVERWRITE:
m_stText.SetAt(m_iEditIndex, (TCHAR) uChar);
break;
}
}
++m_iEditIndex;
GenerateCaretArray(pDC);
}
void TextFigure::GenerateCaretArray(CDC* pDC)
{
CFont cFont;
cFont.CreateFontIndirect(m_font.PointsToMeters());
CFont* pPrevFont = pDC->SelectObject(&cFont);
TEXTMETRIC textMetric;
pDC->GetTextMetrics(&textMetric);
m_iAverageWidth = textMetric.tmAveCharWidth;
if (!m_stText.IsEmpty())
{
m_szText = pDC->GetTextExtent(m_stText);
}
else
{
m_szText.SetSize(textMetric.tmAveCharWidth, textMetric.tmHeight);
}
int iWidth = 0, iSize = m_stText.GetLength();
m_caretArray.SetSize(iSize + 1);
for (int iIndex = 0; iIndex < iSize; ++iIndex)
{
CSize szChar = pDC->GetTextExtent
(m_stText.Mid(iIndex, 1));
m_caretArray[iIndex] = iWidth;
iWidth += szChar.cx;
}
m_caretArray[iSize] = m_szText.cx;
pDC->SelectObject(pPrevFont);
}
CRect TextFigure::GetCaretArea(KeyboardState eKeyboardState)
{
CDrawView *pView = CDrawView::GetView();
CClientDC dc(pView);
pView->OnPrepareDC(&dc);
CFont cFont;
cFont.CreateFontIndirect(m_font.PointsToMeters());
CFont* pPrevFont = dc.SelectObject(&cFont);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
dc.SelectObject(pPrevFont);
switch(m_eTextDirection)
{
case LEFT_TO_RIGHT:
{
CPoint ptCaret(m_ptText.x + m_caretArray[m_iEditIndex],m_ptText.y);
switch (eKeyboardState)
{
case KS_INSERT:
{
CSize szCaret(1, m_szText.cy);
return CRect(ptCaret, ptCaret + szCaret);
}
break;
case KS_OVERWRITE:
{
CSize szCaret(m_iAverageWidth, m_szText.cy);
return CRect(ptCaret, ptCaret + szCaret);
}
break;
}
}
break;
case BOTTOM_TO_TOP:
{
CPoint ptCaret(m_ptText.x ,m_ptText.y + m_caretArray[m_iEditIndex]);
switch (eKeyboardState)
{
case KS_INSERT:
{
CSize szCaret(m_szText.cy,1);
return CRect(ptCaret, ptCaret + szCaret);
}
break;
case KS_OVERWRITE:
{
CSize szCaret(m_szText.cy,m_iAverageWidth);
return CRect(ptCaret, ptCaret + szCaret);
}
break;
}
}
break;
case TOP_TO_BOTTOM:
{
CPoint ptCaret(m_ptText.x - tm.tmHeight,m_ptText.y - m_caretArray[m_iEditIndex]);
switch (eKeyboardState)
{
case KS_INSERT:
{
CSize szCaret(m_szText.cy,1);
return CRect(ptCaret, ptCaret + szCaret);
}
break;
case KS_OVERWRITE:
{
CSize szCaret(m_szText.cy,m_iAverageWidth);
return CRect(ptCaret, ptCaret + szCaret);
}
break;
}
}
break;
}
return CRect();
}
Relevant TableTextFigure codes are:(overrrides TextFigure's draw
#pragma once
#include"..//MyFont.h"
#include"..//Color.h"
#include "TextFigure.h"
class TableTextFigure : public TextFigure
{
public:
TableTextFigure();
TableTextFigure(const Color& color, const CPoint& ptMouse,const MyFont& font, CDC* pDC);
TableTextFigure(const TableTextFigure &text);
Figure* Copy() const;
void Serialize(CArchive& archive);
BOOL Click(const CPoint& ptMouse);
BOOL DoubleClick(const CPoint& ptMouse);
BOOL Inside(const CRect& rcInside) const;
void MoveOrModify(const CSize& szDistance);
void Move(const CSize& szDistance);
void Draw(CDC* pDC) const;
CRect GetArea() const;
BOOL PointInFigure(const CPoint &ptMouse) const;
void SetTextPoint(CPoint &ptText) { m_ptText = ptText;}
BOOL PointInText(const CPoint &ptMouse) const;
void SetFont(const MyFont& font, CDC* pDC);
void SetMyFont(const MyFont& font, CDC* pDC);
};
void TableTextFigure::Draw(CDC* pDC) const
{
CFont cFont;
cFont.CreateFontIndirect(m_font.PointsToMeters());
CFont* pPrevFont = pDC->SelectObject(&cFont);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
if (IsMarked() && !pDC->IsPrinting())
{
pDC->SetTextColor(WHITE);
pDC->SetBkColor(BLUE);
switch(m_eTextDirection)
{
case LEFT_TO_RIGHT:
pDC->TextOut(m_ptText.x, m_ptText.y + m_szText.cy,m_stText);
break;
case BOTTOM_TO_TOP:
pDC->TextOut(m_ptText.x, m_ptText.y + tm.tmHeight + tm.tmExternalLeading - m_szText.cy,m_stText);
break;
case TOP_TO_BOTTOM:
pDC->TextOut(m_ptText.x, m_ptText.y - tm.tmHeight - tm.tmExternalLeading + m_szText.cy,m_stText);
break;
}
}
else
{
pDC->SetTextColor((COLORREF) GetColor());
pDC->SetBkColor(WHITE);
switch(m_eTextDirection)
{
case LEFT_TO_RIGHT:
pDC->TextOut(m_ptText.x, m_ptText.y + m_szText.cy,m_stText);
break;
case BOTTOM_TO_TOP:
pDC->TextOut(m_ptText.x, m_ptText.y + tm.tmHeight + tm.tmExternalLeading - m_szText.cy,m_stText);
break;
case TOP_TO_BOTTOM:
pDC->TextOut(m_ptText.x, m_ptText.y - tm.tmHeight - tm.tmExternalLeading + m_szText.cy,m_stText);
break;
}
}
pDC->SelectObject(pPrevFont);
The relevant View functions are:
void CDrawView::OnKeyDown(UINT uChar, UINT , UINT )
{
CClientDC dc(this);
OnPrepareDC(&dc);
switch (uChar)
{
case VK_HOME:
if (!m_pDrawDoc->KeyDown(VK_HOME, &dc))
{
OnVScroll(SB_TOP, 0, NULL);
OnHScroll(SB_LEFT, 0, NULL);
}
break;
case VK_END:
if (!m_pDrawDoc->KeyDown(VK_END, &dc))
{
OnVScroll(SB_BOTTOM, 0, NULL);
OnHScroll(SB_RIGHT, 0, NULL);
}
break;
case VK_UP:
OnVScroll(SB_LINEUP, 0, NULL);
break;
case VK_DOWN:
OnVScroll(SB_LINEDOWN, 0, NULL);
break;
case VK_LEFT:
if (!m_pDrawDoc->KeyDown(VK_LEFT, &dc))
{
OnHScroll(SB_LINELEFT, 0, NULL);
}
break;
case VK_RIGHT:
if (!m_pDrawDoc->KeyDown(VK_RIGHT, &dc))
{
OnHScroll(SB_LINERIGHT, 0, NULL);
}
break;
case VK_PRIOR:
OnVScroll(SB_PAGEUP, 0, NULL);
break;
case VK_NEXT:
OnVScroll(SB_PAGEDOWN, 0, NULL);
break;
case VK_INSERT:
case VK_DELETE:
case VK_BACK:
case VK_RETURN:
case VK_ESCAPE:
m_pDrawDoc->KeyDown(uChar, &dc);
break;
}
}
void CDrawView::OnChar(UINT uChar, UINT , UINT )
{
CClientDC dc(this);
OnPrepareDC(&dc);
m_pDrawDoc->CharDown(uChar, &dc);
}
The relevant Document functions are:
BOOL CDrawDoc::KeyDown(UINT uChar, CDC* pDC)
{
if (uChar == VK_INSERT)
{
if (m_eKeyboardState == KS_INSERT)
{
m_eKeyboardState = KS_OVERWRITE;
}
else
{
m_eKeyboardState = KS_INSERT;
}
if(m_eApplicationState == EDIT_TABLETEXT)
{
CRect rcCaret = m_pEditTextBox->GetCaretArea(m_eKeyboardState);
m_caret.SetAndShowCaret(rcCaret);
}
return TRUE;
}IT_TEXTBOX)
{
CRect rcCaret = m_pEditTextBox->GetCaretArea(m_eKeyboardState);
m_caret.SetAndShowCaret(rcCaret);
}
if(m_eApplicationState == EDIT_TABLETEXT)
{
CRect rcCaret = m_pEditTextBox->GetCaretArea(m_eKeyboardState);
m_caret.SetAndShowCaret(rcCaret);
}
return TRUE;
}IT_TEXTBOX)
{
CRect rcCaret = m_pEditTextBox->GetCaretArea(m_eKeyboardState);
m_caret.SetAndShowCaret(rcCaret);
}
if(m_eApplicationState == EDIT_TABLETEXT)
{
CRect rcCaret = m_pEditTextBox->GetCaretArea(m_eKeyboardState);
m_caret.SetAndShowCaret(rcCaret);
}
return TRUE;
}
if (m_eApplicationState == EDIT_TABLETEXT)
{
switch (uChar)
{
case VK_LEFT:
case VK_RIGHT:
case VK_HOME:
case VK_END:
case VK_DELETE:
case VK_BACK:
case VK_RETURN:
{
CRect rcOldText = m_pEditTableBox->GetArea();
BOOL bModified = m_pEditTableBox->KeyDown(uChar, pDC);
if (bModified)
{
SetModifiedFlag();
}
CRect rcNewText = m_pEditTableBox->GetArea();
UpdateAllViews(NULL, (LPARAM) &rcOldText);
UpdateAllViews(NULL, (LPARAM) &rcNewText);
CRect rcCaret = m_pEditTableBox->GetCaretArea(m_eKeyboardState);
m_caret.SetAndShowCaret(rcCaret);
}
break;
case VK_ESCAPE:
{
CRect rcText = m_pEditTableBox->GetArea();
m_pEditTableBox->Mark(FALSE);
UpdateAllViews(NULL, (LPARAM) &rcText);
m_caret.HideCaret();
m_pEditTableBox = NULL;
m_eApplicationState = IDLE;
m_eNextActionState = MODIFY_FIGURE;
}
break;
}
return TRUE;
}
int iMarked = m_figurePtrList.CountIf(IsMarked);
if ((uChar == VK_DELETE) && (iMarked > 0))
{
OnDelete();
return TRUE;
}
return FALSE;
}
void CDrawDoc::CharDown(UINT uChar, CDC* pDC)
{
if ((m_eApplicationState == EDIT_TABLETEXT) && isprint(uChar))
{
m_caret.HideCaret();
if(m_pEditTableBox->GetTable()->GetEditCell()->GetCaretFlag())
{
return;
}
try
{
m_pEditTableBox->CharDown(uChar, pDC, m_eKeyboardState);
}
catch(BOOL bSkip)
{
m_pEditTableBox->GetTable()->GetEditCell()->SetCaretFlag(bSkip);
return;
}
CRect rcText = m_pEditTableBox->GetArea();
CRect rcCaret = m_pEditTableBox->GetCaretArea(m_eKeyboardState);
m_caret.SetAndShowCaret(rcCaret);
UpdateAllViews(NULL, (LPARAM) &rcText);
SetModifiedFlag();
}
}
The prototype of relevant TableFigure,Table, TCell,TableText classes are all the same:All each does to call get the relvant data member functions whicha are all public function: A sample prototype for TCell is shown below:
void TCell::CharDown(UINT uChar, CDC *pDC, KeyboardState m_eKeyboardState)
BOOL TCell::KeyDown(UINT uChar, CDC* pDC)
So what really happens in the code is that, The view class calls the document class; the document class class calls its CharDown function and its CharDown function call the CharDown function of the Tablefigure object which goes on to eventually call the CharDown figure of the TableTextFigure.
So, what could be wrong