Visual KB「MFC Windowsプログラム設計例」

11521 ワード

//filename:VisualKB.h



#define MAX_STRING 12



class CMyApp:public CWinApp{

public:

	virtual BOOL InitInstance();

};





class CMainWindow:public CWnd

{



protected:

	int m_cxChar;				//Average character width

	int m_cyChar;				//Character height

	int m_cyLine;				//Vertical line spacing in message box

	int m_nTextPos;				//Index of current character for tabbed output

	int m_nTabStops[7];			//Tab stop locations for tabbed output

	int m_nTextLimit;			//Maximum width of text in text box

	int m_nMsgPos;				//Current position in m_strMessages array



	HCURSOR m_hCursorArrow;		//Handle of arrow cursor

	HCURSOR m_hCursorIBeam;		//Handle of I-Beam cursor



	CPoint m_ptTextOrigin;		//Origin for drawing input text

	CPoint m_ptHeaderOrigin;	//Origin for drawing header text

	CPoint m_ptUpperMsgOrigin;	//Origin of first line in message box

	CPoint m_ptLowerMsgOrigin;	//Origin of first line in message box

	CPoint m_ptCaretPos;		//Current caret position



	CRect m_rcTextBox;			//Coordinates of text box

	CRect m_rcTextBoxBorder;	//Coordinates of text box border

	CRect m_rcMsgBoxBorder;		//Coordinates of message box border

	CRect m_rcScroll;			//Coordinates of scroll rectangle



	CString m_strInputText;						//Input text

	CString m_stringMessages[MAX_STRING];		//Array Of message strings



public:

	CMainWindow();

protected:

	int GetNearestPos(CPoint point);

	void PositionCaret(CDC * pDC=NULL);

	void DrawInputText(CDC * pDC);

	void ShowMessage(LPCTSTR pszMessage,UINT nChar,UINT nRepCnt,

		UINT nFlags);

	void DrawMessageHeader(CDC * pDC);

	void DrawMessage(CDC * pDC);

	void DrawMessages(CDC * pDC);

protected:

	virtual void PostNcDestroy();



	afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);

	afx_msg void OnPaint ();

	afx_msg void OnSetFocus(CWnd* pWnd);	//old wnd

	afx_msg void OnKillFocus(CWnd* pWnd);	//new wnd

	afx_msg BOOL OnSetCursor(CWnd *pWnd,UINT nHitTest,UINT message);

	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

	afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);

	afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

	afx_msg void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);

	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);

	afx_msg void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags);



	DECLARE_MESSAGE_MAP()

};


 
 
//filename:VisualKB.cpp



#include <afxwin.h>

#include "VisualKB.h"



CMyApp myApp;



//CMyApp member functions



BOOL CMyApp ::InitInstance()

{

	m_pMainWnd = new CMainWindow;

	m_pMainWnd ->ShowWindow(m_nCmdShow);

	m_pMainWnd->UpdateWindow();

	return TRUE;

}



/////////////////////////////////////////////////////////

//CMainWindow message map and number functiosn



BEGIN_MESSAGE_MAP(CMainWindow,CWnd)

	ON_WM_CREATE()

	ON_WM_PAINT()

	ON_WM_SETFOCUS()

	ON_WM_SETFOCUS()

	ON_WM_KILLFOCUS()

	ON_WM_SETCURSOR()

	ON_WM_LBUTTONDOWN()

	ON_WM_KEYDOWN()

	ON_WM_KEYUP()

	ON_WM_SYSKEYDOWN()

	ON_WM_SYSKEYUP()

	ON_WM_CHAR()

	ON_WM_SYSCHAR()

END_MESSAGE_MAP()





CMainWindow::CMainWindow()

{

	m_nTextPos = 0;

	m_nMsgPos = 0;



	m_hCursorArrow = AfxGetApp()->LoadStandardCursor(IDC_ARROW);

	m_hCursorIBeam = AfxGetApp()->LoadStandardCursor(IDC_IBEAM);



	//register a WNDCLASS

	CString strWndClass = AfxRegisterWndClass(

		0,

		NULL,

		(HBRUSH)(COLOR_3DFACE + 1),

		AfxGetApp()->LoadStandardIcon(IDI_WINLOGO)

	);

	

	//create a window

	CreateEx(0,strWndClass,_T("Visual Keyboard"),

		WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,

		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,

		NULL,NULL

		);

}





int CMainWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

	if(CWnd::OnCreate(lpCreateStruct)==-1)

	{

		return -1;

	}

	CClientDC dc(this);

	TEXTMETRIC tm;

	dc.GetTextMetrics(&tm);

	m_cxChar = tm.tmAveCharWidth;

	m_cyChar = tm.tmHeight;

	m_cyLine = tm.tmHeight + tm.tmExternalLeading;



	m_rcTextBoxBorder.SetRect(16,16,(m_cxChar*64)+16,

		((m_cyChar*3)/2)+16

	);

	m_rcTextBox = m_rcTextBoxBorder;

	m_rcTextBox.InflateRect(-2,-2);



	m_rcMsgBoxBorder.SetRect(16, (m_cyChar*4)+16,

		(m_cxChar * 64)+16,(m_cyLine * MAX_STRING)+(m_cyChar * 6)+16

		);

	m_rcScroll.SetRect(m_cxChar + 16,(m_cyChar * 4)+16,

		(m_cxChar * 64)+16, (m_cyLine * MAX_STRING )

		+ (m_cyChar * 6) + 16

		);

	m_ptTextOrigin.x = m_cxChar + 16;

	m_ptTextOrigin.y = (m_cyChar /4 )+16;

	m_ptCaretPos = m_ptTextOrigin;

	m_nTextLimit = (m_cxChar * 63)+16;



	m_ptHeaderOrigin.x = m_cxChar + 16;

	m_ptHeaderOrigin.y = (m_cyChar * 3)+16;



	m_ptUpperMsgOrigin.x = m_cxChar + 16;

	m_ptUpperMsgOrigin.y = m_cyChar * 5 + 16;



	m_ptLowerMsgOrigin.x = m_cxChar + 16;

	m_ptLowerMsgOrigin.y = (m_cyChar * 5)

		+ m_cyLine * (MAX_STRING -1)+16;



	m_nTabStops[0] = (m_cxChar * 24) + 16;

	m_nTabStops[1] = (m_cxChar * 30) + 16;

	m_nTabStops[2] = (m_cxChar * 36) + 16;

	m_nTabStops[3] = (m_cxChar * 42) + 16;

	m_nTabStops[4] = (m_cxChar * 46) + 16;

	m_nTabStops[5] = (m_cxChar * 50) + 16;

	m_nTabStops[6] = (m_cxChar * 54) + 16;



	CRect rect(0,0,m_rcMsgBoxBorder.right + 16,

		m_rcMsgBoxBorder.bottom + 16);

	CalcWindowRect(&rect);

	SetWindowPos(NULL,0,0,rect.Width() ,rect.Height(),

		SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);

	return 0;

}



void CMainWindow::PostNcDestroy()

{

	delete this;

}



void CMainWindow::OnPaint()

{

	CPaintDC dc(this);



	dc.DrawEdge(m_rcTextBoxBorder,EDGE_SUNKEN,BF_RECT);

	dc.DrawEdge(m_rcMsgBoxBorder,EDGE_SUNKEN,BF_RECT);



	DrawInputText(&dc);

	DrawMessageHeader(&dc);

	DrawMessage(&dc);

}



void CMainWindow::OnSetFocus(CWnd* pWnd){

	CreateSolidCaret(max(2,::GetSystemMetrics(SM_CXBORDER)),

		m_cyChar);

	SetCaretPos(m_ptCaretPos);

	ShowCaret();

}



void CMainWindow::OnKillFocus(CWnd* pWnd){

	HideCaret();

	m_ptCaretPos = GetCaretPos();

	::DestroyCaret();

}



BOOL CMainWindow::OnSetCursor(CWnd *pWnd,UINT nHitTest,UINT message)

{

	if(nHitTest == HTCLIENT)

	{

		DWORD dwPos = ::GetMessagePos();

		CPoint point(LOWORD(dwPos),HIWORD(dwPos));

		ScreenToClient(&point);

		::SetCursor(m_rcTextBox.PtInRect(point)?

				m_hCursorIBeam:m_hCursorArrow);

		return TRUE;

	}

	return CWnd::OnSetCursor(pWnd,nHitTest,message);

}



void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point)

{

	if(m_rcTextBox.PtInRect(point))

	{

		m_nTextPos = GetNearestPos(point);

		PositionCaret();

	}

}



void CMainWindow::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

{

	ShowMessage(_T("WM_KEYDOWN"),nChar,nRepCnt,nFlags);



	switch (nChar)

	{

	case VK_LEFT:

		if(m_nTextPos !=0){

			m_nTextPos --;

			PositionCaret();

		}

		break;

	case VK_RIGHT:

		if(m_nTextPos != m_strInputText.GetLength())

		{

			m_nTextPos++;

			PositionCaret();

		}

		break;

	case VK_HOME:

		m_nTextPos = 0;

		PositionCaret();

		break;

	case VK_END:

		m_nTextPos = m_strInputText.GetLength();

		PositionCaret();

		break;

	}

}



void CMainWindow::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

	ShowMessage(_T("WM_CHAR"),nChar,nRepCnt,nFlags);

	CClientDC dc(this);



	switch (nChar)

	{

	case VK_ESCAPE:

	case VK_RETURN:

		m_strInputText.Empty();

		m_nTextPos = 0;

		break;

	case VK_BACK:

		if(m_nTextPos != 0)

		{

			m_strInputText = m_strInputText.Left(m_nTextPos-1)

				+m_strInputText.Right(m_strInputText.GetLength()

				- m_nTextPos);

			m_nTextPos--;

		}

		break;

	default:

		if((nChar>=0) && (nChar <= 31))

			return;

		if(m_nTextPos == m_strInputText.GetLength())

		{

			m_strInputText += nChar;

			m_nTextPos ++;

		}

		else 

			m_strInputText.SetAt(m_nTextPos++,nChar);



		CSize size = dc.GetTextExtent(m_strInputText,

			m_strInputText.GetLength());

		if((m_ptTextOrigin.x + size.cx) > m_nTextLimit)

		{

			m_strInputText = nChar;

			m_nTextPos = 1;

		}

		break;

	}



	HideCaret();

	DrawInputText(&dc);

	PositionCaret(&dc);

	ShowCaret();

}



void CMainWindow::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)

{

	ShowMessage(_T("WM_KEYUP"),nChar,nRepCnt,nFlags);

	CWnd::OnKeyUp(nChar,nRepCnt,nFlags);

}



void CMainWindow::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

{

	ShowMessage(_T("WM_SYSKEYDOWN"),nChar,nRepCnt,nFlags);

	CWnd::OnSysKeyDown(nChar,nRepCnt,nFlags);

}

void CMainWindow::OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

	ShowMessage(_T("WM_SYSCHAR"),nChar,nRepCnt,nFlags);

	CWnd::OnSysChar(nChar,nRepCnt,nFlags);

}

void CMainWindow::OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)

{

	ShowMessage(_T("WM_SYSKEYUP"),nChar,nRepCnt,nFlags);

	CWnd::OnSysKeyUp(nChar,nRepCnt,nFlags);

}



void CMainWindow :: PositionCaret(CDC * pDC/* =NULL */)

{

	BOOL bRelease = FALSE;

	if(pDC == NULL){

		pDC = GetDC();

		bRelease = true;

	}



	CPoint point = m_ptTextOrigin;	

	CString string = m_strInputText.Left(m_nTextPos);

	point.x += (pDC ->GetTextExtent(string,string.GetLength())).cx;

	SetCaretPos(point);



	if(bRelease) ReleaseDC(pDC);

}



int CMainWindow::GetNearestPos(CPoint point)

{

	if(point.x  <= m_ptTextOrigin.x) return 0;



	CClientDC dc(this);

	int nLen = m_strInputText.GetLength();

	if(point.x >= (m_ptTextOrigin.x+dc.GetTextExtent(m_strInputText,nLen).cx)) return nLen;

	

	int i=0;

	int nPrevChar = m_ptTextOrigin.x;

	int nNextChar = m_ptTextOrigin.x;

	while(nNextChar < point.x){

		i++;

		nPrevChar = nNextChar;

		nNextChar = m_ptTextOrigin.x + 

			dc.GetTextExtent(m_strInputText.Left(i),i).cx;



	}

	return point.x - nPrevChar < nNextChar - point.x ? i-1 : i ;

}





void CMainWindow::DrawInputText(CDC * pDC)

{

	pDC ->ExtTextOut(m_ptTextOrigin.x,m_ptTextOrigin.y,

		ETO_OPAQUE,m_rcTextBox,m_strInputText,NULL);

}



void CMainWindow::ShowMessage(LPCTSTR pszMessage,UINT nChar,UINT nRepCnt, UINT nFlags)

{

	CString string;

	string.Format(_T("%s\t %u\t %u\t %u\t %u\t %u\t %u\t %u"),

		pszMessage,nChar,nRepCnt,nFlags & 0xFF,

		(nFlags >> 8 ) & 0x01,

		(nFlags >> 13) & 0x01,

		(nFlags >> 14) & 0x01,

		(nFlags >> 15) & 0x01

		);



	ScrollWindow(0,-m_cyLine,&m_rcScroll);

	ValidateRect(m_rcScroll);



	CClientDC dc(this);

	dc.SetBkColor((COLORREF)::GetSysColor(COLOR_3DFACE));

	m_stringMessages[m_nMsgPos] = string;

	dc.TabbedTextOut(m_ptLowerMsgOrigin.x,m_ptLowerMsgOrigin.y,

		m_stringMessages[m_nMsgPos],m_stringMessages[m_nMsgPos].GetLength(),

		sizeof(m_nTabStops),m_nTabStops , m_ptLowerMsgOrigin.x);



	if(++m_nMsgPos == MAX_STRING) m_nMsgPos = 0;

}



void CMainWindow ::DrawMessageHeader(CDC * pDC)

{

	static CString string = _T("Message\tChar\tRep\tScan\tExt\tCan\tPrv\tTran");

	pDC->SetBkColor((COLORREF)::GetSysColor(COLOR_3DFACE));

	pDC->TabbedTextOut(m_ptHeaderOrigin.x,m_ptHeaderOrigin.y,

		string,string.GetLength(),sizeof(m_nTabStops),m_nTabStops,m_ptHeaderOrigin.x);

}



void CMainWindow::DrawMessage(CDC * pDC)

{

	int nPos = m_nMsgPos;

	pDC->SetBkColor((COLORREF)::GetSysColor(COLOR_3DFACE));

	for(int i=0;i<MAX_STRING;i++){

		pDC->TabbedTextOut(m_ptUpperMsgOrigin.x,

			m_ptUpperMsgOrigin.y + m_cyLine*i,

			m_stringMessages[nPos],

			m_stringMessages[nPos].GetLength(),

			sizeof(m_nTabStops),m_nTabStops,m_ptUpperMsgOrigin.x);

		if(++nPos == MAX_STRING) nPos = 0;

	}

}