MFCブロッキングメッセージ(Editコントロール技術の修正)

4370 ワード

説明:既存のコントロールの機能の変更->サブクラス化テクノロジーSetWindowLong()、CallWindowProc()
カスタムCDoubleEditクラス
ヘッダファイル
#pragma once
class CDoubleEdit
{
public:
	CDoubleEdit();
	~CDoubleEdit();

BOOL Attach(HWND hWnd);//       

void DeAttach();//    

BOOL GetStringValue(LPTSTR lpBuffer,int nLen);//       

BOOL GetDoubleValue(double* dValue);
protected:
	static LRESULT APIENTRY NewEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);//     
protected:
	HWND m_hWnd;
	long m_lOldProc;
};

インプリメンテーションファイル
#include "stdafx.h"
#include "DoubleEdit.h"

#define DOUBLE_EDIT_PROP_NAME _T("Double_Edit_Prop_Name")
CDoubleEdit::CDoubleEdit()
{
}
CDoubleEdit::~CDoubleEdit()
{
	DeAttach();
}
BOOL CDoubleEdit::Attach(HWND hWnd)
{
	if (m_hWnd!=NULL)
	{
		DebugBreak();
		return FALSE;
	}
	m_hWnd = hWnd;
	SetProp(hWnd, DOUBLE_EDIT_PROP_NAME,this);
	m_lOldProc = SetWindowLong(hWnd, GWL_WNDPROC, (long)NewEditProc);
	if (m_lOldProc==0)
	{
		m_lOldProc = NULL;
		return FALSE;
	}
	return TRUE;
}

//        
LRESULT APIENTRY CDoubleEdit::NewEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)//     
{
	CDoubleEdit* pEdit = (CDoubleEdit*)GetProp(hWnd, DOUBLE_EDIT_PROP_NAME);
	if (pEdit == NULL)
	{
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}

	BOOL bCanceled = FALSE;

	//         
	if (uMsg==WM_CHAR)
	{
		TCHAR szBuff[32] = { 0 };
		pEdit->GetStringValue(szBuff, 32);
		switch (wParam)
		{
		case '.':
			if (_tcschr(szBuff,'.'))
			{
				bCanceled = TRUE;
			}
			break;
		case '-':
			if (_tcschr(szBuff, '-'))
			{
				bCanceled = TRUE;
			}
			else if (LOWORD(SendMessage(hWnd,EM_GETSEL,0,0))!=0)
			{
				bCanceled = TRUE;
			}
			break;
		default:
			if ((wParam>'9') || (wParamm_lOldProc, hWnd, uMsg, wParam,lParam);
}

BOOL CDoubleEdit::GetStringValue(LPTSTR lpBuffer, int nLen){
	return GetWindowText(m_hWnd,lpBuffer,nLen);
}

BOOL CDoubleEdit::GetDoubleValue(double* dValue)
{
	TCHAR szBuf[32];
	if (GetStringValue(szBuf, 32))
	{
		*dValue = _tstof(szBuf);
	}
	else
	{
		return FALSE;
	}
}

void CDoubleEdit::DeAttach(){
	if (m_hWnd==NULL)
	{
		return;
	}
	SetWindowLong(m_hWnd, GWL_WNDPROC, m_lOldProc);
	m_hWnd = NULL;
	m_lOldProc = 0;
}




//     Dlg.cpp :     
//

#include "stdafx.h"
#include "    .h"
#include "    Dlg.h"
#include "afxdialogex.h"
#include "DoubleEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// C    Dlg    
CDoubleEdit g_edit;


C    Dlg::C    Dlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(C    Dlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void C    Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(C    Dlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDOK, &C    Dlg::OnBnClickedOk)
	ON_WM_DESTROY()
END_MESSAGE_MAP()


// C    Dlg       

BOOL C    Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	//          。                ,     
	//       
	SetIcon(m_hIcon, TRUE);			//      
	SetIcon(m_hIcon, FALSE);		//      

	// TODO:              
	g_edit.Attach(GetDlgItem(IDC_EDT_TEST)->GetSafeHwnd());
	return TRUE;  //           ,     TRUE
}

//              ,        
//        。        /      MFC     ,
//           。

void C    Dlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); //           

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);

		//             
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		//     
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//                      
//  。
HCURSOR C    Dlg::OnQueryDragIcon()
{
	return static_cast(m_hIcon);
}



void C    Dlg::OnBnClickedOk()
{
	// TODO:                
	//  
	double dValue = 0.0;
	if (g_edit.GetDoubleValue(&dValue))
	{
		TCHAR szBuf[128] = { 0 };
		_stprintf(szBuf, _T("     :%.10f"), dValue);
		AfxMessageBox(szBuf);
	}
	else
	{
		AfxMessageBox(_T("    "));
	}
	//CDialogEx::OnOK();
}


void C    Dlg::OnDestroy()
{
	CDialogEx::OnDestroy();

	// TODO:               
	g_edit.DeAttach();
}