※ [] 안에 표시된 명칭이 Visual Studio 2015의 도구-옵션-환경-키보드에서 지정할 위치


Goto implementation(Alt+G) : 함수 원형 및 함수 구현 위치로 보내줌 [편집.정의로이동]

Open H <-> CPP(Alt+O) : .h파일과 .cpp파일 사이를 왔다갔다 하게 해줌 [편집기상황에맞는메뉴.코드창.헤더코드파일전환]

Popup context menu(Shift+오른쪽마우스) : va 확장 메뉴 보여줌

List method in current file(Alt+M) : 현재 파일의 모든 method 리스트를 보여줌

Dlg open file in workspace(Shift+Alt+O) : warkspace에 존재하는 모든 파일 리스트를 보여줌

Back(Alt+Left Arrow) : 브라우져에서처럼 뒤로 돌아가기를 실행한다. [보기.뒤로탐색]

Forward(Alt+Right Arrow) : 브라우져처럼 앞으로 가기를 실행한다. [보기.앞으로탐색]

Paste Multiple(Shift+Ctrl+V) : 멀티플 클립보드 버퍼 내용을 보여주고 paste할 수 있게 한다. 

Find Next(Alt+Shift+F3) : 현재 마우스커서가 가르키고 있는 Symbol을 이후에서 찾는다.

블로그 이미지

요다할아범

,

[Tips] Win32 콘솔 애플리케이션에서 MFC class들을 사용하기

  5 Comments

이미 잘 알려진 내용이지만 제 블로그의 검색을 위해 짧게 포스팅합니다.

Visual Studio 6.0에서 Win32 콘솔 애플리케이션 (Console Application)으로 프로젝트를 만들어 표준 C/C++ 라이브러리를 이용할 때 MFC (Microsoft Foundation Class Library)의 클래스들 (e.g. CString, CObList)을 이용하는 방법입니다.

1. CRT (C Run-Time) library를 Multithreaded로 변경

  1. Alt+F7을 누르거나 메뉴의 Project / Setting을 선택해서 “Project Settings” 창을 띄웁니다.
  2. “C/C++” 탭에서 “Category”를 “Code Generation”이라고 선택합니다.
  3. 아래 그림과 같이 “Use run-time library”를 “Debug Multithreaded”로 변경합니다. 
    ※ 물론 릴리즈 모드인 경우는 Multithreaded를 선택하겠죠.

MFC 클래스를 위한 헤더 파일들을 포함시켜도 링크 에러가 나는 것은 Win32 console application 프로젝트는 기본적으로 “Single-Threaded” CRT library를 사용해서 멀티스레드를 위한 api 구현이 없기 때문입니다. 그래서 이와 같이 CRT 라이브러리를 변경하는 것입니다.

2. 필요한 헤더 파일 포함

사용할 MFC 클래스를 정의하고 있는 헤더 파일들을 포함합니다.

※ MFC의 헤더 파일과 라이브러리 설명은 Devpia의 이 글을 참고하시면 됩니다.

간단히 많은 것을 포함하는 헤더 파일들만 설명드리면..

Afx.h: MFC를 위한 main header file로 컨테이너를 비롯한 많은 MFC 클래스들을 선언합니다.

Afxtempl.h: CArray등 템플릿을 요하는 클래스들의 선언을 가지고 있습니다.

간단히 CString이나 CObList를 사용하는 경우는 Afx.h를 포함하면 될 것이고

CArry, CList등 템플릿 컨테이너 클래스를 사용할 경우는 Afxtempl.h를 포함하면됩니다.

순서는 Afx.h가 먼저 오는 것이 좋겠죠? (순서가 바뀌어도 컴파일 에러는 나지 않으나…)

// MFC main header file. for CString, CObList, etc
#include <afx.h>

// MFC template based container class. for CArray, CList, etc
#include <afxtempl.h>
#include <iostream>

void main()
{
CString str;
CObList list;
CArray<CString, CString> ar;
str.Format(“test CString: %s”, “temp string”);
std::cout<<(LPCSTR)str<<std::endl;
}


블로그 이미지

요다할아범

,

컨테이너 간의 복사는 자료형이 다르더라도 카피 알고리즘에 의하여 호환성을 지닌다. 
주의할 점은 덮의 씌워지는 대상의 객체의 사이즈가 원본컨테이너의 사이즈보다 같거나 커야한다. 
copy알고리즘을 사용하기전에 resize명령어로 컨테이너의 사이즈를 꼭 재조정 하도록 한다.

다음예제는 컨테이너와 컨테이너간에 값을 덮어 씌우는 방법이다.(추가가 아님!)

#include "stdafx.h"

#include <iostream>
#include <list>
#include <vector>
#include <deque>
#include <algorithm>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
 list<int> a1;
 vector<int> a2;

 for(int i = 0; i < 10; ++i)
  a1.push_back(i);
 
 a2.resize(a1.size());
 copy(a1.begin(), a1.end(), a2.begin());

 deque<int> a3(a1.size());
 copy(a1.begin(), a1.end(), a3.begin());

 for(int i = 0; i < 10; ++i)
  cout << a2[i] << ' ' << a3[i] << ' ';

 cout << endl;
 return 0;
}


다음 예제는 컨테이너에 반복자 어댑터를 사용하여 새로운 원소를 추가하는 방법이다.
미리 정의된 삽입 반복자에는 3가지가 있다
back_inserter(container) - push_back()을 사용하여 뒷부분에 추가시킨다
front_inserter(container) - push_front()를 사용하여 앞부분에 추가시킨다
inserter(container, pos) - insert()를 사용하여 pos위치에 삽입한다.

#include "stdafx.h"

#include <iostream>
#include <list>
#include <vector>
#include <deque>
#include <set>
#include <algorithm>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
 list<int> a1;

 for(int i = 0; i < 10; ++i)
  a1.push_back(i);

 //a1의 모든 원소들을 a2에 뒷부분으로 추가한다.
 vector<int> a2;
 copy(a1.begin(), a1.end(), back_inserter(a2));

 //a1의 모든 원소들을 a3에 앞부분으로 추가한다.
 deque<int> a3;
 copy(a1.begin(), a1.end(), front_inserter(a3));

 //a1의 원소들을 a4에 복사한다.
 //연관 컨테이너는 오직 inserter()와만 동작한다.
 set<int> a4;
 copy(a1.begin(), a1.end(), inserter(a4.begin());
 return 0;
}

블로그 이미지

요다할아범

,

/*

std::list<CUser *> l1;

std::vector<CUser *> v1;


for( nSeed = 0; nSeed < MAX_SEED; nSeed++ )

{

l1.assign( m_QueUser[ nSeed ].GetListInactive()->GetList()->begin(), m_QueUser[ nSeed ].GetListInactive()->GetList()->end() );

v1.resize( l1.size() );

std::copy( l1.begin(), l1.end(), v1.begin() );

for( INT8 n = 0; n < RAND(v1.size()); n++ )

std::random_shuffle( v1.begin(), v1.end() );


std::list<CUser *> l2(v1.begin(), v1.end()); // 다른 방법: std::copy(v1.begin(), v1.end(), std::inserter(l1, l1.begin()));

m_QueUser[ nSeed ].GetListInactive()->GetList()->clear();

m_QueUser[ nSeed ].GetListInactive()->GetList()->assign( l2.begin(), l2.end() );

l1.clear();

l2.clear();

v1.clear();

}

//*/


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

// INT8 i;

// TRACE("==START=================================================================================\n" );

// for( i = 0; i < 1; i++ )

// {

// CSync Sync( m_QueUser[ i ].GetListInactive()->GetSync() );

// CSyncList<CUser>::SYNC_POSITION pos = m_QueUser[ i ].GetListInactive()->GetHeadPosition();

// while( !m_QueUser[ i ].GetListInactive()->IsEnd( pos ) )

// {

// CUser *pUser = m_QueUser[ i ].GetListInactive()->GetItem( pos++ );

// if( pUser )

// {

// TRACE(" %s\n", pUser->m_szUserID );

// }

// }

// }

// 

// TRACE("==std::list=================================================================================\n" );

// std::list<CUser *> l1;

// l1.assign( m_QueUser[ 0 ].GetListInactive()->GetList()->begin(), m_QueUser[ 0 ].GetListInactive()->GetList()->end() );

// std::list<CUser *>::iterator iterEnd = l1.end();

// for( std::list<CUser *>::iterator iterPos = l1.begin(); iterPos != iterEnd; ++iterPos )

// {

// CUser *pUser = *iterPos;

// if( pUser )

// {

// TRACE(" %s\n", pUser->m_szUserID );

// }

// }

// 

// TRACE("==std::vector=&=std::vector:random_shuffle()====================================================\n" );

// std::vector<CUser *> v1;

// v1.resize( l1.size() );

// std::copy( l1.begin(), l1.end(), v1.begin() );

// for( INT8 n = 0; n < RAND(v1.size()); n++ )

// std::random_shuffle( v1.begin(), v1.end() );

//

// std::vector<CUser *>::iterator vEnd = v1.end();

// for( std::vector<CUser *>::iterator vPos = v1.begin(); vPos != v1.end(); ++vPos )

// {

// CUser *pUser = *vPos;

// if( pUser )

// {

// TRACE(" %s\n", pUser->m_szUserID );

// }

// }

// 

// TRACE("==END=================================================================================\n" );

// std::list<CUser *> l2(v1.begin(), v1.end()); // 다른 방법: std::copy(v1.begin(), v1.end(), std::inserter(l1, l1.begin()));

//

// m_QueUser[ 0 ].GetListInactive()->GetList()->clear();

// m_QueUser[ 0 ].GetListInactive()->GetList()->assign( l2.begin(), l2.end() );

// 

// for( i = 0; i < 1; i++ )

// {

// CSync Sync( m_QueUser[ i ].GetListInactive()->GetSync() );

// CSyncList<CUser>::SYNC_POSITION pos = m_QueUser[ i ].GetListInactive()->GetHeadPosition();

// while( !m_QueUser[ i ].GetListInactive()->IsEnd( pos ) )

// {

// CUser *pUser = m_QueUser[ i ].GetListInactive()->GetItem( pos++ );

// if( pUser )

// {

// TRACE(" %s\n", pUser->m_szUserID );

// }

// }

// }

// 

// l1.clear();

// l2.clear();

// v1.clear();

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

블로그 이미지

요다할아범

,
아래의 내용을 reg 파일로 저장하여 실행하면
레지스트리에 내용이 생성되고 폰트가 변경된다.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Format]

[HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Format\Output Window]
"FontFace"="Consolas"
"FontSize"=dword:0000000c

[HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Format\Source Window]
"FontFace"="Consolas"
"FontSize"=dword:0000000c
[HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Format\Workspace Window]
"FontFace"="Tahoma"
"FontSize"=dword:00000008



블로그 이미지

요다할아범

,