'개발이야기/MFC'에 해당되는 글 13건

  1. Microsoft Visual C++ 2005 Service Pack 1 재배포 가능 패키지 설치 6
  2. MFC 버튼 마우스 커서 변경
  3. fopen_s 파일읽기와 저장
  4. MFC 디렉토리 생성과 삭제
  5. 뮤텍스를 이용한 프로그램 중복실행 방지
  6. 일정 날짜 기준 로그파일 제거 1
  7. 로컬 IP주소 얻기
  8. 유니코드 ↔ 안시 변환함수
  9. 폴더선택 다이얼로그와 초기폴더경로 설정
  10. MFC Control 오픈소스 모음


Window7 환경에서 Visual C++ 2005 재배포 가능 패키지를 설치하려고 하였을때 다음과 같은 오류가 나타났다.

(Command line option syntax error. Type Command /? for Help.)


종래 해결 방법으로 설치 파일을 C:또는 D: 드라이브에 옮기고 나서 콘솔 창에서

"vcredist_x86.exe /t:c:temp" 와 같은 명령어를 사용하여 설치하려고 하였지만 이후에 창이 닫혀버리고

실제 설치되지 않는 문제가 발생하였다.


이곳 저곳으로 문제 해결점을 찾아보았지만, 딱히 해결 방법을 못찾아 다시 마소사이트에서 재배포 패키지를 검색해보니

Microsoft Visual C++ 2005 Service Pack 1 재배포 가능 패키지 MFC 보안 업데이트 버전이 있는것이 아닌가 !

(http://www.microsoft.com/ko-kr/download/details.aspx?id=26347)


MFC 보안 업데이트 버전으로 다운로드 받아 설치하였더니 경고창 없이 깨끗하게 설치되었고 적용도 잘 되었다 :)




간단한 코드 추가로 위 그림과 같이 버튼의 커서를 변경시킬 수 있습니다.

변경하고자 하는 버튼의 컨트롤 변수를 만들고, OnInitDialog 함수에 다음과 같이 코드를 추가합니다.


  
BOOL CTestDlg::OnInitDialog()
{
	// 자동으로 생성되는 코드는 생략합니다.
	// TODO: 여기에 추가 초기화 작업을 추가합니다.

	// 버튼의 마우스 커서 변경
	// (m_ctrlButton: 해당 버튼의 컨트롤 변수)
	HCURSOR hCursor; 
	hCursor = AfxGetApp()->LoadStandardCursor(IDC_HAND); 
	SetClassLong(m_ctrlButton.GetSafeHwnd(),GCL_HCURSOR,(LONG)hCursor);

	return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}


SetClassLong 함수는 해당 윈도우 핸들을 통하여 클래스 정보를 수정하는 함수입니다.

이를 통해 버튼 클래스의 커서 정보를 수정하는 원리입니다.



fopen_s 함수를 이용하여 파일을 읽는 코드와 저장하는 코드입니다.


  
//
// fopen_s 파일읽기
//
errno_t err;
FILE *fp;
if( (err = fopen_s(&fp, "file_path", "rt")) != 0 )
{
	AfxMessageBox(_T("File open error!"));
	return false;
}

fscanf_s(fp,"format", ...); // 사용법은 c의 scanf함수와 동일
fclose(fp)

//
// fopen_s 파일저장
//
errno_t err;
FILE *fp;
if( (err = fopen_s(&fp, "file_path", "wt")) != 0 )
{
	AfxMessageBox(_T("File open error!"));
	return ;
}

fprintf_s(fp,"format", ...); // 사용법은 c의 printf함수와 동일
fclose(fp)


특히 fscanf_s 함수를 사용하여 문자열을 읽어올때 c의 scanf함수 사용법과 동일하지 않습니다.

이와 관련하여 다음 링크를 참조하세요.

fscanf_s 주의사항: http://mooyou.tistory.com/6



MFC코드 기반 디렉토리 생성과 삭제 코드 입니다.

디렉토리 삭제 참조: http://sanaigon.tistory.com/120

  
//
// 디렉토리 생성
// 디렉토리 생성 성공: TRUE, 실패: FALSE 반환
// 함수 사용예: CreateDir(_T("C:\\dir_name\\"));
//
BOOL CreateDir(CString dir)
{
	CFileFind file;
	CString strFile = _T("*.*");
	BOOL bResult = file.FindFile(dir + strFile);

	if(!bResult)
	{
		bResult = CreateDirectory(dir, NULL);
	}

	return bResult;
}

//
// 디렉토리 삭제
// 디렉토리내에 존재하는 하위 폴더 및 모든 파일 삭제
// 함수 사용예: DeleteDir(_T("C:\\dir_name\\*.*"));
//
BOOL DeleteDir(CString dir)
{
	if(dir == _T(""))
	{
		return FALSE;
	}

	BOOL bRval = FALSE;
	int nRval = 0;
	CString szNextDirPath = _T("");
	CString szRoot = _T("");
	CFileFind find;

	// Directory가 존재 하는지 확인 검사
	bRval = find.FindFile(dir);

	if(bRval == FALSE)
	{
		return bRval;
	}

	while(bRval)
	{
		bRval = find.FindNextFile();

		// . or .. 인 경우 무시한다.
		if(find.IsDots() == TRUE)
		{
			continue;
		}

		// Directory 일 경우
		if(find.IsDirectory())
		{
			szNextDirPath.Format(_T("%s\\*.*"), find.GetFilePath());

			// Recursion function 호출
			DeleteDir(szNextDirPath);
		}

		// file일 경우
		else
		{
			//파일 삭제
			::DeleteFile(find.GetFilePath());
		}
	}

	szRoot = find.GetRoot();
	find.Close();

	Sleep(1);
	bRval = RemoveDirectory(szRoot);

	return bRval;
}



헤더파일: App Class (.h)

  
// 뮤텍스 핸들 선언
protected:
	HANDLE m_hMutex;


소스파일: App Class (.cpp)

  
#define STRING_MUTEX_NAME		"뮤텍스 이름"
#define STRING_CAPTION_NAME		"프로그램 이름(Caption)"

//
// 생성자 뮤텍스 핸들 초기화
//
CClassApp::CClassApp()
{
	m_hMutex = NULL;
}

//
// 프로그램 중복실행 방지
//
CClassApp::InitInstance()
{
	if(NULL == ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, STRING_MUTEX_NAME))
	{
		// 중복실행이 아니므로 뮤택스 생성
		m_hMutex = ::CreateMutex(NULL, FALSE, STRING_MUTEX_NAME);
		if(m_hMutex == NULL)
		{
			AfxMessageBox(_T("프로그램 실행에 실패하였습니다."), MB_OK|MB_ICONEXCLAMATION);
			return FALSE;
		}
	}
	else
	{
		// 중복실행일 경우 기존 열려있는 창을 맨 앞으로 보여줌
		// 만약, 창이 최소화 상태라면 최소화 상태 해제
		CWnd*  pWnd = NULL;
		pWnd = CWnd::FindWindow(NULL, STRING_CAPTION_NAME);
		if(pWnd != NULL)
		{
			if(pWnd->IsIconic()) 
				pWnd->ShowWindow(SW_RESTORE);
			else     
				pWnd->SetForegroundWindow();
		}
		else
		{
			pWnd = CWnd::FindWindow(NULL, STRING_CAPTION_NAME);
			if(pWnd != NULL)
			{
				if(pWnd->IsIconic()) 
					pWnd->ShowWindow(SW_RESTORE);
				else     
					pWnd->SetForegroundWindow();
			}
		}
		return FALSE;
	}  

	// 기존 코드
}


'개발이야기 > MFC' 카테고리의 다른 글

fopen_s 파일읽기와 저장  (0) 2012.06.14
MFC 디렉토리 생성과 삭제  (0) 2012.05.25
일정 날짜 기준 로그파일 제거  (1) 2012.05.17
로컬 IP주소 얻기  (0) 2012.05.17
유니코드 ↔ 안시 변환함수  (0) 2012.05.16


본 코드는 30일이 지난 로그파일을 삭제합니다.

강조된 부분의 코드수정을 통해 제거 일정 기준을 변경시킬 수 있습니다.

  
//
// 폴더 경로 얻음
//
CString GetFolderPath(CString path)
{
	if(path.Right(1) == _T('\\'))
	{
		return path;
	}
	else
	{
		CString strFolderPath;
		strFolderPath = path.Left(path.ReverseFind(_T('\\'))+1);
		return strFolderPath;
	}
}

//
// 일정 날짜 기준 로그파일 제거
//
void DeleteLogfiles()
{
	// 로그파일 형태 20111116.log
	// 30일 기준 로그파일 삭제
	CTime CurTime = CTime::GetCurrentTime();
	CTime Day30Time;
	Day30Time = CurTime - CTimeSpan(30, 0, 0, 0); // 일, 시, 분, 초
	CString path, file_path, file_name;
	path.Format(_T("%s*.*"), _("로그디렉토리경로\\"));
	CFileFind finder;
	BOOL bRes;
	bRes = finder.FindFile(path);
	while(bRes)
	{
		bRes = finder.FindNextFile();
		if(!finder.IsDirectory()) // 폴더가 아니고 파일일 경우
		{
			// 삭제 상태 변수 초기화
			bool bDelete = false;
			// 현재 정보가 파일인 경우, file_data.cFileName에 파일이름이 들어있다.
			file_name = finder.GetFileName();
			file_path = GetFolderPath(path) + file_name;
			CString strLogDate;
			strLogDate = file_name.Left(8);
			// 문자 길이가 맞고, 숫자로만 구성되었는지 확인
			if(strLogDate.GetLength() == 8 && IsStringDigit(strLogDate))
			{
				int nLogYear = _ttoi(strLogDate.Left(4));
				int nLogMonth = _ttoi(strLogDate.Mid(4, 2));
				int nLogDay = _ttoi(strLogDate.Right(2));
				CTime LogTime(nLogYear, nLogMonth, nLogDay, 0, 0, 0, 0);
				if(LogTime < Day30Time)
					bDelete = true;
			}
			else
			{
				// 예외사항
				bDelete = true;
			}    
			if(bDelete)
			{
				// 30일이 지난 로그파일은 삭제
				DeleteFile(file_path);
			}
		}
	}
}



로컬 IP주소를 얻을 수 있는 함수입니다.

CString 타입으로 _T("xxx.xxx.xxx.xxx")와 같이 반환합니다.

  
#include <afxsock.h>
CString GetIPAddress()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	char name[255];
	CString ip; // 여기에 lcoal ip가 저장됩니다.
	PHOSTENT hostinfo;
	wVersionRequested = MAKEWORD( 2, 0 );
	if ( WSAStartup( wVersionRequested, &wsaData ) == 0 ) 
	{
		if( gethostname ( name, sizeof(name)) == 0)
		{
			if((hostinfo = gethostbyname(name)) != NULL)
			{
				ip = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);
			}
		}      
		WSACleanup( );
	} 
	return ip;
}



VS2008을 사용하게되면서 UNICODE와 ANCI간의 스트링 상호변환 함수를 정리한 것입니다.

프로젝트 문자집합 속성(유니코드, 멀티바이트)에 상관없이 변환 가능합니다.

  
//
// CString → Char
//
char* StringToChar(CString str)
{
	char *szStr = NULL;
#if defined(UNICODE) || defined(_UNICODE)
	int nLen = str.GetLength() + 1;
	TCHAR *tszTemp = NULL;
	tszTemp = new TCHAR[nLen];
	memset(tszTemp, 0x00, nLen*sizeof(TCHAR));
	_tcscpy(tszTemp, str);
	// Get size (실제사용되는바이트사이즈)
	int nSize = WideCharToMultiByte(CP_ACP, 0, tszTemp, -1, NULL, NULL, NULL, NULL);
	szStr = new char[nSize];
	memset(szStr, 0x00, nSize);
	WideCharToMultiByte(CP_ACP, 0, tszTemp, -1, szStr, nSize, NULL, NULL);
	if(tszTemp)
	{
		delete [] tszTemp;
		tszTemp = NULL;
	}
#else
	int nLen = str.GetLength() + 1;
	szStr = new char[nLen];
	memset(szStr, 0x00, nLen);
	strcpy(szStr, str);
#endif
	return szStr;
}

//
// CString → TCHAR
//
TCHAR* StringToTCHAR(CString str)
{
	TCHAR *tszStr = NULL;
	int nLen = str.GetLength() + 1;
	tszStr = new TCHAR[nLen];
	memset(tszStr, 0x00, nLen*sizeof(TCHAR));
	_tcscpy(tszStr, str);

	return tszStr;
}

//
// Char → CString
//
CString CharToString(char *str)
{
	CString cStr;
#if defined(UNICODE) || defined(_UNICODE)
	int nLen = strlen(str) + 1;
	TCHAR *tszTemp = NULL;
	tszTemp = new TCHAR[nLen];
	memset(tszTemp, 0x00, nLen*sizeof(TCHAR));
	MultiByteToWideChar(CP_ACP, 0, str, -1, tszTemp, nLen*sizeof(TCHAR));
	cStr.Format(_T("%s"), tszTemp);
	if(tszTemp)
	{
		delete [] tszTemp;
		tszTemp = NULL;
	}
#else
	cStr.Format("%s", str);
#endif
	return cStr;
}

//
// Char → TCHAR
//
TCHAR* CharToTCHAR(char *str)
{
	TCHAR *tszStr = NULL;
#if defined(UNICODE) || defined(_UNICODE)
	int nLen = strlen(str) + 1;
	tszStr = new TCHAR[nLen];
	memset(tszStr, 0x00, nLen*sizeof(TCHAR));
	MultiByteToWideChar(CP_ACP, 0, str, -1, tszStr, nLen*sizeof(TCHAR));
#else
	int nLen = strlen(str) + 1;
	tszStr = new TCHAR[nLen];
	memset(tszStr, 0x00, nLen*sizeof(TCHAR));
	_tcscpy(tszStr, str);
#endif
	return tszStr;
}

//
// TCHAR → CString
//
CString TCHARToString(TCHAR *str)
{
	CString cStr;
	cStr.Format(_T("%s"), str);
	return cStr;
}

//
// TCHAR → Char
//
char* TCHARToChar(TCHAR *str)
{
	char *szStr = NULL;
#if defined(UNICODE) || defined(_UNICODE)
	int nSize = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, NULL, NULL, NULL);
	szStr = new char[nSize];
	memset(szStr, 0x00, nSize);
	WideCharToMultiByte(CP_ACP, 0, str, -1, szStr, nSize, NULL, NULL);
#else
	int nLen = strlen(str) + 1;
	szStr = new char[nLen];
	memset(szStr, 0x00, nLen);
	strcpy(szStr, str);
#endif
	return szStr;
}


'개발이야기 > MFC' 카테고리의 다른 글

일정 날짜 기준 로그파일 제거  (1) 2012.05.17
로컬 IP주소 얻기  (0) 2012.05.17
폴더선택 다이얼로그와 초기폴더경로 설정  (0) 2012.05.15
MFC Control 오픈소스 모음  (0) 2012.05.13
3D 다이아몬드  (0) 2012.05.13


//
// 폴더선택 다이얼로그를 구현하기 위해 사용되는 사용자정의 Callback 함수
//
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
	switch (uMsg) {
		// 폴더선택 다이얼로그의 초기화가 끝난 경우
	case BFFM_INITIALIZED:
		SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
		break;
	}
	return 0;
}

//
// 폴더선택 다이얼로그
//
void SelectFolder()
{
	ITEMIDLIST	*pidlBrowse;
	WCHAR		pszPathname[MAX_PATH];

	BROWSEINFO	BrInfo;
	BrInfo.hwndOwner = GetSafeHwnd();
	BrInfo.pidlRoot = NULL;

	memset(&BrInfo, 0x00, sizeof(BrInfo));
	BrInfo.pszDisplayName = pszPathname;
	BrInfo.lpszTitle = _T("Select folder");
	BrInfo.ulFlags = BIF_RETURNONLYFSDIRS;

	// 이벤트에 대한 사용자정의 함수
	BrInfo.lpfn = BrowseCallbackProc;

	// 사용자정의 함수에 넘겨질 인자로 사용자가 설정하고자 하는 경로를 설정한다.
	// 예를들어 초기폴더경로를 C드라이브로 설정하는 경우
	CString strInitPath = _T("C:\\");
	BrInfo.lParam = (LPARAM)strInitPath.GetBuffer();

	pidlBrowse = ::SHBrowseForFolder(&BrInfo);
	if(pidlBrowse != NULL)
	{
		// 선택된 폴더 경로얻음
		SHGetPathFromIDList(pidlBrowse, pszPathname);
		
		// 경로(pszPathname)를 이용하여 이후작업 추가
	}
}


'개발이야기 > MFC' 카테고리의 다른 글

로컬 IP주소 얻기  (0) 2012.05.17
유니코드 ↔ 안시 변환함수  (0) 2012.05.16
MFC Control 오픈소스 모음  (0) 2012.05.13
3D 다이아몬드  (0) 2012.05.13
MD5 Checksum 모듈  (0) 2012.05.13

'개발이야기 > MFC' 카테고리의 다른 글

유니코드 ↔ 안시 변환함수  (0) 2012.05.16
폴더선택 다이얼로그와 초기폴더경로 설정  (0) 2012.05.15
3D 다이아몬드  (0) 2012.05.13
MD5 Checksum 모듈  (0) 2012.05.13
fscanf_s 주의사항  (0) 2012.05.12