ADO Import, msado15.dll 추가방법
MFC&ActiveX 2016. 2. 29. 22:31 |stdafx.h 파일에
#import "C:\Program Files\Common Files\System\ado\msado15.dll" rename("EOF", "EndOfFile") no_namespace
이 구문을 추가 한다.
stdafx.h 파일에
#import "C:\Program Files\Common Files\System\ado\msado15.dll" rename("EOF", "EndOfFile") no_namespace
이 구문을 추가 한다.
MFC의 Dialog 베이스를 사용해서 폼을 하나 제작합니다.
그리고 picture Box 를 하나 제작한 후에 CxImage를 사용해서 png 파일을 하나 로드 한후에
picture Box에 SetBitmap 를 하고 나서 이걸 다른 형태로 테스트를 진행해 봤습니다.
기본 코드는 아래와 같아요.
// CxImage 객체 생성
m_pImage = new CxImage("D:\\Test.png", CXIMAGE_FORMAT_PNG);
// PictureBox 컨트롤에 CxImage 이미지 연동
m_pic.SetBitmap( m_pImage->MakeBitmap() );
이렇게 하고 나서 실행 하고, 종료 하게 되면 크게 문제는 안되는듯 하다.
이걸 다른 형태로 테스트를 해봤다.
타이머를 통해서 CxImage 객체 두개의 Bitmap를 m_pic(PictureBox) 컨트롤에 SetBitmap를 반복해서 처리해봤다.
void CPngToBitmapDlg::OnTimer(UINT nIDEvent)
{
static bool bFirst = false;
static HBITMAP hBitmap = NULL;
if( bFirst == false )
{
hBitmap = m_pic.SetBitmap( m_pImage2->MakeBitmap() );
}
else
{
hBitmap = m_pic.SetBitmap( m_pImage->MakeBitmap() );
}
::DeleteObject( hBitmap );
//
bFirst = !bFirst;
m_loopCount++;
UpdateData(false);
CDialog::OnTimer(nIDEvent);
}
위의 붉은색 코드를 하지 않고 계속해서 SetBitmap을 하게 되면
페이지파일(PF)가 계속 증가 하는 것을 볼 수 있다.
앞으로 코드 구현을 할때 하나 하나 단위테스트를 통해서 반복적인 메모리 및 GDI 사용량 등을
체크 하고 좀 안정성 있는 프로그램을 하도록 해야 할거 같다.
void ChoiceDirectoryPath(char* pathFolder)
{
ASSERT( pathFolder );
sprintf( pathFolder, "" );
//CString m_strDirPath;
ITEMIDLIST *pidlBrowse;
char pszPathname[MAX_PATH];
BROWSEINFO BrInfo;
BrInfo.hwndOwner = NULL; //GetSafeHwnd();
BrInfo.pidlRoot = NULL;
memset( &BrInfo, 0, sizeof(BrInfo) );
BrInfo.pszDisplayName = (LPSTR)pszPathname;
BrInfo.lpszTitle = _T("폴더를 선택해 주세요.");
BrInfo.ulFlags = BIF_RETURNONLYFSDIRS;
// 다이얼로그 뛰우기
pidlBrowse = SHBrowseForFolder(&BrInfo);
if(pidlBrowse != NULL)
{
BOOL bSuccess = ::SHGetPathFromIDList(pidlBrowse, (LPSTR)pszPathname);
if( bSuccess )
{
sprintf( pathFolder, "%s", pszPathname );
}
}
}
// 사용할때
char szDirectory[MAX_PATH];
ZeroMemory( szDirectory, sizeof(szDirectory) );
ChoiceDirectoryPath( szDirectory );
if( strlen(szDirectory) <= 0 )
return 0;
void CDlgProgPage::OnBnClickedBtnProgBackgroundload()
{
// 이미지 로드 - 여기에 오픈 다이얼로그를 적용해야징.
// 이미지가 로드 되고 나면 화면을 업데이트 한다.
CFileDialog OpenDlg( TRUE, "Add Files", "*.*", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT,
"Bitmap Files(*.*)|*.bmp|Jpeg Files(*.*)|*.jpg|PNG Files(*.*)|*.png|AVI Files(*.*)|*.avi|All Files(*.*)|*.*|" );
if( OpenDlg.DoModal() == IDOK )
{
// 이미지 정보를 View로 보낸다.
g_ProgView->SetBackgroundImage(GetImage(OpenDlg.GetPathName()));
// 백그라운드 이미지가 있다면 체크박스 속성을 활성화 한다.
CheckBackgroundImage();
}
}
특정 폴더를 기준으로 하위 폴더를 찾아 내는 코드 입니다.
그리고 그 폴더 내용을 xml 형태로 만들어 주는 코드도 포함되어 있습니다.
xml 데이터로 만들어진 내용은 CEdit 컨트롤에 표시되며, 그 내용을
저장할 수 있습니다.
MFC에서 xml 데이터를 읽어 들이는 예제입니다.
아래의 내용을 계층구조를 통해서 읽어 들이게 됩니다.
자세한 소스는 소스 코드를 참조 하세요.
- XmlParser.h, cpp
[xml 샘플]
<?xml version="1.0" encoding="EUC-KR"?>
<PATHS>
<PATH NAME="Install Files">
<PATH NAME="Dev">
</PATH>
<PATH NAME="Dev2">
</PATH>
<PATH NAME="Dev3">
<PATH NAME="Dev3_a">
</PATH>
<PATH NAME="Dev3_b">
<PATH NAME="Dev3_b_a">
</PATH>
<PATH NAME="Dev3_b_b"/>
</PATH>
</PATH>
</PATH>
<PATH NAME="temp">
<PATH NAME="temp_a"/>
<PATH NAME="temp_b">
<PATH NAME="temp_b_a">
</PATH>
<PATH NAME="temp_b_b">
<PATH NAME="temp_b_c"/>
</PATH>
</PATH>
</PATH>
</PATHS>
계층 구조를 읽어 들이는 코드 (재귀호출)
1. 초기화 및 도입부
///
MSXML2::IXMLDOMNodePtr nodeList = m_pDoc->selectSingleNode( Token.c_str() );
_bstr_t bsElements("PATHS");
if ( nodeList )
FindName( nodeList->GetchildNodes() );
nodeList.Release();
2. 재귀호출 부분
int tabCount = 0;
HRESULT CXmlParser::FindName( MSXML2::IXMLDOMNodeListPtr& lparam )
{
long elementCount = lparam->Getlength();
for( int i = 0; i < elementCount; i++ )
{
MSXML2::IXMLDOMElementPtr Element = lparam->nextNode();
if( Element == NULL )
break;
_bstr_t bsNodename = Element->GetnodeName();
_bstr_t bsElement("PATH");
if( bsNodename == bsElement )
{
_bstr_t bsname("NAME");
_variant_t varElementName = Element->getAttribute(bsname);
// 해당하는 엘러먼트 Name의 이름 == 폴더 이름을 의미한다.
CString strName;
strName.Format( "%S", varElementName.bstrVal );
// 탭 카운터를 통한 출력
CString strTabMergy;
for( int tc = 0; tc < tabCount; tc++ )
{
strTabMergy += "\t";
}
strTabMergy += strName;
TRACE( "%s\n", (LPSTR)(LPCSTR)strTabMergy);
MSXML2::IXMLDOMNodeListPtr childElementlist = Element->GetchildNodes();
if( childElementlist )
{
tabCount++;
FindName( childElementlist );
}
}
Element.Release();
}
tabCount--;
lparam.Release();
return S_OK;
}
아래의 콘솔 화면 내용입니다.
이제 설명을 시작하겠습니다.
Ruler 보완
Ruler의 기존 소스를 보게 되면 마우스로 스크롤 할때 Ruler가 따라 가지 않습니다.
기존 코드를 볼가요?
// 기본 Ruler
CRect rulerRect;
rulerRect.left = scrollPosition.x;
rulerRect.right = rulerRect.left + curArea.Width();
rulerRect.top = scrollPosition.y;
rulerRect.bottom = rulerRect.top + 20;
m_RulerHorz.Draw( pDC, rulerRect.left, rulerRect.top, rulerRect.Width(), rulerRect.Height(), scrollPosition.x );
분명히 scrollPosition.y를 해줬는데도 안됩니다.
이걸 해결 하기 위해서는 휠을 움직여서 화면을 업데이트 한 것이기 때문에
아래의 OnMouseWheel함수를 오버라이드(?) 해서 Invalidate()를 해줘야 됩니다.
BOOL CRulerSampleView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
Invalidate();
return CScrollView::OnMouseWheel(nFlags, zDelta, pt);
}
그리고 Scroll의 Bar를 움직여도 화면이 업데이트 되어야 하기 때문에 아래의 함수들도 같이 처리
void CRulerSampleView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
Invalidate( true );
CScrollView::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CRulerSampleView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
Invalidate( true );
CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
}
이렇게 하고 나면 휠 또는 스크롤바를 움직여도 Ruler가 자연스럽게 화면에 보이는걸 알 수 있습니다.
자자..
이제 줌인 줌아웃 처리를 해볼까요..
줌인 줌아웃 처리를 위해서 아래의 코드를 RulerSampleView.h 에 추가 합니다.
CSize m_PageSize;
float m_Zoom;
그리고 RulerSampleView.cpp 에는 아래와 같이 해봅시다.
> 우선 줌 성분 초기화를 생성자 함수에 추가
m_Zoom = 1.f;
> ScrollVew이기 때문에 페이지의 크기를 추가
void CRulerSampleView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
m_PageSize = CSize( 1000, 1000 );
SetScrollSizes(MM_TEXT, m_PageSize);
}
> 드로잉 코드에 m_Zoom을 적절하게 수정해 줍니다.
테스트를 위한 위치값을 10개를 생성했습니다. 이건 코드 보시면 알수 있어요..
드로잉 할때 아래와 같이 처리 합니다.
vector< CPoint >::iterator iter;
for( iter = m_TestData.begin(); iter != m_TestData.end(); iter++ )
{
CRect rect;
rect.left = (*iter).x;
rect.top = (*iter).y;
rect.right = rect.left + 50;
rect.bottom = rect.top + 50;
rect.left *= m_Zoom;
rect.top *= m_Zoom;
rect.right *= m_Zoom;
rect.bottom *= m_Zoom;
pDC->FillRect( &rect, &redbrush );
}
위의 붉은 부분을 m_Zoom으로 곱해줍니다.
> 이렇게 하고 나서 이제 이벤트를 추가해줘야 겠죠.
방향키를 통해서 줌인 줌아웃 성분을 증가 감소 합니다.
void CRulerSampleView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if( nChar == VK_UP )
{
m_Zoom -= 0.1f;
CClientDC dc(this);
m_RulerHorz.CreateDC( &dc, 10000, 20, m_Zoom );
m_PageSize = CSize( 1000*m_Zoom, 1000*m_Zoom );
SetScrollSizes(MM_TEXT, m_PageSize);
Invalidate();
}
if( nChar == VK_DOWN )
{
m_Zoom += 0.1f;
CClientDC dc(this);
m_RulerHorz.CreateDC( &dc, 10000, 20, m_Zoom );
m_PageSize = CSize( 1000*m_Zoom, 1000*m_Zoom );
SetScrollSizes(MM_TEXT, m_PageSize);
Invalidate();
}
CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}
위의 코드에서 보듯이 Ruler도 줌 성분이 달라지면, Ruler의 줌 성분을 보정해서 메모리 DC를 생성합니다.
그리고 ScrollView의 페이지도 m_Zoom에 따라서 사이즈를 제조정 해줍니다.
이렇게 하면 아래와 같은 프로그램을 만들 수 있습니다.
흑백의 이미지를 CxImage로 만들때 8비트, 24비트의 이미지로 만들 필요가 없습니다.
이때 1비트의 이미지로 해도 충분한 공간이 나온다는 얘긴데요.
아래의 코드는 1비트의 이미지를 생성하는 코드 입니다.
void GToleranceImage::MakeBuffer2Image()
{
SAFE_DELETE( _pbuffer2Image );
assert( _pbuffer2Image == NULL );
// 넓이와 폭을 사용해서 이미지 버퍼를 생성합니다.
// 이때 1비트의 이미지로 설정합니다.
_pbuffer2Image = new CxImage( _width, _height, 1, CXIMAGE_FORMAT_BMP );
// 이미지의 팔레트를 지정합니다.
// 흑백 이미지를 만들거기 때문에 0번과 1번 팔레트를 설정합니다.
_pbuffer2Image->SetPaletteColor(0, RGB(0, 0, 0));
_pbuffer2Image->SetPaletteColor(1, RGB(255, 255, 255));
// 해당 내용을 추가합니다.
// SetPixelColor로 하지 않고, SetPixelIndex로 하게 됩니다.
for( int y = 0; y < _height; y++ )
{
for( int x = 0; x < _width; x++ )
{
BYTE color = _bufferXY[y][x];
if( color == 255 )
_pbuffer2Image->SetPixelIndex( x, y, 1 );
else
_pbuffer2Image->SetPixelIndex( x, y, 0 );
}
}
_pbuffer2Image->Flip();
}
이외의 생성자 인자로서는 해당 width, height를 입력해줄 수 있으며,
내부 코드에서는 해당 다이얼로그에 맞도록 리셈플링 처리가 되어 있습니다.
실행파일 :
1.요약 데이터를 암호화하는 방법에는 여러가지가 있는데 가장 간단한 방법이 배타적 논리합(Exclusive OR)를 이용하는 방법이 있습니다. 이 방법은 너무 간단해서 보안에 치명적이죠. 특별한 암호방법을 고안해낼려면 그쪽 분야에 많은 연구와 노력이 필요한데 저를 포함해 대부분 암호화에 대한 지식이 거의 전무할겁니다. 저같은 사람들을 위해 MS에서 암호화를 위한 API를 제공하고 있습니다. 하지만 이것도 사용하기가 너무 복잡하고 여러 단계를 거져야하는 불편함이 있습니다. 그래서 최대한 사용하기 간단하게 Class로 만들어 보았습니다. 2.본문 먼저 암호에 필요한 API함수는 어떤것이 있는지 알아보겠습니다. BOOL WINAPI CryptAcquireContext(HCRYPTPROV *phProv, LPCTSTR Container, LPCTSTR pszProvider, DWORD dwProvType, DWORD dwFlags); BOOL WINAPI CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, CRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash); BOOL WINAPI CryptHashData(HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags); BOOL WINAPI CryptDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey); BOOL WINAPI CryptEncrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen); BOOL WINAPI CryptDecrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen); 자세한 사용법은 MSDN을 참고하세요. 이러한 API의 사용법을 설명하지 않겠습니다. 사실 저도 자세히는 모름니다. Class 멤버 함수와 사용법을 소개드리겠습니다. BOOL CCrypt::Create(LPBYTE pHashData, DWORD dwHashDataLen)- 암호화나 해독에 필요한 Key를 생성하는 함수. 쉽게 여기에 Password가 들어간다고 생각하면 됩니다. void CCrypt::Destroy()- Create에서 만들어진 Handle을 제거합니다. BOOL CCrypt::Encrypt(LPBYTE lpBuffer, DWORD& dwBufferLen, BOOL bFanal)- 데이터를 암호화하는 함수 BOOL CCrypt::Decrypt(LPBYTE lpBuffer, DWORD& dwBufferLen, BOOL bFanal)- 암호화된 데이터를 해독하는 함수 3.예제 dwDataLen = strPassword.GetLength(); CopyMemory(lpData, (LPVOID)(LPCTSTR)strPassword, strPassword.GetLength()); // 암호화 CCrypt Crypt; Crypt.Create((LPBYTE)(LPCTSTR)strPassword, strPassword.GetLength()); Crypt.Encrypt(lpData, dwDataLen); Crypt.Destroy(); // 암호화된 데이터 해독 Crypt.Create((LPBYTE)(LPCTSTR)strPassword, strPassword.GetLength()); Crypt.Decrypt(lpData, dwDataLen); lpData[dwDataLen] = '\0'; |