정리

Visual Studio에서 리소스 편집의 영향을 받는 파일(aps 파일은 뭐냐?)

저장소/VC++

출처 : MSDN http://msdn.microsoft.com/ko-kr/library/fywbdhak(v=vs.90).aspx


Visual Studio에서 리소스 편집의 영향을 받는 파일


Visual Studio 개발 환경에서는 리소스 편집 세션 중 다음 표에 있는 파일에 대한 작업을 수행합니다.

파일 이름

설명

Resource.h

개발 환경에서 만들어지는 헤더 파일로, 기호 정의가 포함됩니다.

Filename.aps

현재 리소스 스크립트 파일의 바이너리 버전으로, 빠른 로드를 위해 사용됩니다.

리소스 편집기에서 .rc 파일이나 resource.h 파일을 직접 읽을 수는 없습니다.
리소스 컴파일러가 이 파일을 리소스 편집기에서 사용할 수 있도록 .aps 파일로 컴파일합니다.
.aps 파일은 기호화된 데이터만 저장하는 컴파일 단계 파일입니다. 일반적인 컴파일 과정에서처럼,
주석과 같이 기호가 아닌 정보는 컴파일할 때 삭제됩니다. .aps 파일이 .rc 파일과 동기화되지 않으면
그 때마다 .rc 파일이 다시 생성됩니다. 예를 들어, 저장할 때
리소스 편집기는 .rc 파일과 resource.h 파일을 덮어씁니다.
리소스의 변경 내용은 모두 .rc 파일에 저장되지만 주석은 .rc 파일을 덮어쓸 때 삭제됩니다.
주석을 보존하는 방법은 
컴파일 타임에 리소스 포함을 참조하십시오.

.rc

현재 프로젝트에 있는 리소스의 스크립트가 포함된 리소스 스크립트 파일.
저장할 때마다 .aps 파일이 이 파일을 덮어씁니다.

 


'저장소 > VC++' 카테고리의 다른 글

ifstream 한글 문제  (0) 2012.10.30
[STL] string, wstring의 assign을 이용한 문자열 변환  (0) 2012.10.30
boost 관련 참고할만한 링크  (0) 2012.09.12
deprecated 설정  (0) 2012.09.11
Windows 권한  (0) 2012.08.20

boost 관련 참고할만한 링크

저장소/VC++


boost 스마트 포인터 파헤치기 : http://blog.naver.com/sorkelf/40132656978

흥배님의 다양한 boost 예제 : http://jacking75.cafe24.com/Boost/libraries.htm

boost 입문 : http://mech12.springnote.com/pages/690403


deprecated 설정

저장소/VC++
deprecated : 중요도가 떨어져 더 이상 사용되지 않고 앞으로는 사라지게 될(신조어) - by 네이버 영어사전


[Visual C++ Language Reference]

How to use:
__declspec(deprecated) or __declspec(deprecated("do not use"))

(Microsoft specific) With the exceptions noted below, the deprecated declaration offers the same functionality as the deprecated pragma:

  • The deprecated declaration lets you specify particular forms of function overloads as deprecated, whereas the pragma form applies to all overloaded forms of a function name.

  • The deprecated declaration lets you specify a message that will display at compile time. The text of the message can be from a macro.

  • Macros can only be marked as deprecated with the deprecated pragma.

If the compiler encounters the use of a deprecated identifier, a C4996 warning is thrown.


The following sample shows how to mark functions as deprecated, and how to specify a message that will be displayed at compile time, when the deprecated function is used.

// deprecated.cpp
// compile with: /W3
#define MY_TEXT "function is deprecated"
void func1(void) {}
__declspec(deprecated) void func1(int) {}
__declspec(deprecated("** this is a deprecated function **")) void func2(int) {}
__declspec(deprecated(MY_TEXT)) void func3(int) {}

int main() {
   func1();
   func1(1);   // C4996
   func2(1);   // C4996
   func3(1);   // C4996
}

The following sample shows how to mark classes as deprecated, and how to specify a message that will be displayed at compile time, when the deprecated class is used.

// deprecate_class.cpp
// compile with: /W3
struct __declspec(deprecated) X {
   void f(){}
};

struct __declspec(deprecated("** X2 is deprecated **")) X2 {
   void f(){}
};

int main() {
   X x;   // C4996
   X2 x2;   // C4996
}



간단하게 말하자면 앞으로 사용하지 않을, 지원하지 않을, 삭제될 예정인 타입, 클래스, 함수 등을 컴파일 타임에 Warnning으로 처리되어 알리는 역할을 한다. 대충 보니 2003 부터 지원했던 것 같다. 그냥 그러하다.


#pragma deprecated

이런 것도 있는데 귀찮으니 다음에...




Windows 권한

저장소/VC++


출처 : 백발의 개발자님 블로그

Windows 권한 이해하기 1 : http://blog.naver.com/jjoommnn/130029014466

Windows 권한 이해하기 2 : http://blog.naver.com/jjoommnn/130029072191

Windows 권한 이해하기 3 : http://blog.naver.com/jjoommnn/130029485318

Windows 권한 이해하기 4 : http://blog.naver.com/jjoommnn/130029660867

Windows 권한 이해하기 예제 : http://blog.naver.com/jjoommnn/130041930878


게시물 없어지기 전에 내용 복사 예정, 헤헤

[C++] RTTI와 dynamic_cast

저장소/VC++

문제는 어쨋든 해결 했으나 정확한 원인을 파악하지 못했기에 남겨둔다.


RTTI는 Run-time Type Information 다. 그냥 그렇다구.

dynamic_cast를 사용하기 위해서는 /GR 옵션을 사용해야 한다. 맞나?

visual studio 6.0은 프로젝트 설정에서 따로 옵션을 추가하거나 사용을 체크해줘야 한다.

visual studio 2008은 기본 설정으로 되어있다. 더 자세한 내용은 그냥 검색하든가 책을 보자.


문제는 dynamic_cast를 사용하는 환경에는 아무 문제가 없는데 문제가 발생했다는거.

상속도 정상적이었고 생성도 문제 없었음.

업 캐스팅은 문제가 없었으나 다운 캐스팅을 할 때 NULL이 반환됨.

컴파일 과정에서 어떠한 경고나 에러 발생하지 않았음.

모든 상황을 다 확인했으나 문제 없어보였음.

결국 함수 단위로 쪼개서 테스트 해보니


error C2243: '형식 캐스팅' 발생!


원인은 상속받을 때 다음과 같이 했다는거.


class Book{};

class Bible : Book{};


이게 뭣이당가! public 빼먹었더니만 캐스팅 할 때 바로 문제가 나오는데!

왜 아무런 경고나 에러가 발생하지 않았었을까?

link 할 때 뭔가 잘못 된 것 같긴 한데 정확한 원인을 모르겠다!! @_@


'저장소 > VC++' 카테고리의 다른 글

deprecated 설정  (0) 2012.09.11
Windows 권한  (0) 2012.08.20
[Win32 API] 메모리 유효성 검증(사용 금지)  (0) 2012.06.20
Windows XP sp2 환경에서 exe 또는 dll 사용 시 재부팅 문제  (0) 2012.06.13
[MFC] CDockablePane  (0) 2012.02.10

InstallShield 대신할 Freeware Installer

저장소/잡다한거

InstallShield를 대신해서 쓸만한 Installer들이다.


NSIS : http://nsis.sourceforge.net

Inno Setup : http://www.jrsoftware.org


둘 다 스크립트를 작성하여 구성하는 형태.

Third-Party에서 만든 IDE 프로그램도 각각 있으니 찾아봐라.

'저장소 > 잡다한거' 카테고리의 다른 글

Syntax Highlighter 적용 방법  (0) 2012.11.09
ASCII Table  (0) 2012.10.17
InstallShield Script - Global Event Handler  (0) 2011.05.06
Syntax Highlighter Test  (0) 2011.01.24
[MS Dos] 파일 내 특정 문자열 찾기  (0) 2011.01.04

[Win32 API] 메모리 유효성 검증(사용 금지)

저장소/VC++

참고 : http://blog.naver.com/winjks/10030145808


IsBadCodePtr : 현재의 프로세스가 해당 주소가 가리키는 영역을 읽을 수 있는지.
IsBadReadPtr : 현재의 프로세스가 해당 주속가 가리키는 영역을 읽을 수 있는지.
IsBadStringPtr : 현재의 프로세스가 해당 주속가 가리키는 영역을 문자열로 읽을 수 있는지의 여부 확인.
시작포인터로 부터 null이 나올때까지 유효성을 검사
IsBadWritePtr : 현재의 프로세스가 해당 주속가 가리키는 영역에 기록할 수 있는지.


하지만!!
MSDN을 보면 다음과 같은 내용이 있다.
나중에 언제 없어질지 몰라요~
그냥 쓰지 말자. ㅡㅜ

Important This function is obsolete and should not be used. Despite its name, it does not guarantee that the pointer is valid or that the memory pointed to is safe to use. For more information, see Remarks on this page.

Windows XP sp2 환경에서 exe 또는 dll 사용 시 재부팅 문제

저장소/VC++

Windows XP sp2 환경에서 exe 또는 dll 사용 시 재부팅 문제.

내가 찾은거 아니지만 정리..


MS 원문 : http://support.microsoft.com/kb/921337


Windows XP 서비스 팩 2(SP2)에서 Windows Vista 확장이 포함된 매니페스트를 .exe 또는 .dll 파일에 추가하면 컴퓨터가 다시 시작될 수 있다


Microsoft Windows Vista 확장이 포함된 매니페스트를 .exe 또는 .dll 파일에 추가하면 컴퓨터가 다시 시작될 수 있습니다. 이 문제는 Microsoft Windows XP 서비스 팩 2(SP2) 기반 컴퓨터에서 발생합니다. 또한 .exe 파일이 실행되거나 .dll 파일이 로드되는 경우에도 이 문제가 발생합니다. Microsoft Windows Vista 확장이 포함된 매니페스트 세그먼트의 예제는 다음과 같습니다.

//The section between >>>>> and <<<< is the problematic section. 

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Synergex.Synergyde.lm" type="win32"> 
</assemblyIdentity> 
<dependency> 
<dependentAssembly> 
<assemblyIdentity 
   type="win32" name="Microsoft.VC80.CRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"> 
</assemblyIdentity> 
</dependentAssembly> 
</dependency> 

>>>>>>>>>>> 

<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3" xmlns="urn:schemas-microsoft-com:asm.v3"> 
<ms_asmv3:security xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3"> 
<requestedPrivileges> 
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"> 
</requestedExecutionLevel> 
</requestedPrivileges> 
</ms_asmv3:security> 
</ms_asmv3:trustInfo> 

<<<<<<<<<<< 

</assembly> 

이 문제는 Csrss.exe에서 Windows Vista 확장이 포함된 매니페스트를 포함하는 .exe 파일이나 .dll 파일을 로드하는 경우 
발생합니다. Csrss.exe에서 포함된 매니페스트의 구문을 분석할 때 두 스키마 속성이 있는 단일 태그를 발견하면 내부 메모리가 손상될 수 
있습니다. 위의 예제에서 두 스키마 속성이 포함된 태그는 다음과 같습니다. 
<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3" xmlns="urn:schemas-microsoft-com:asm.v3">
Csrss.exe에서 이러한 태그를 발견하면 메모리 손상으로 인해 액세스 위반이 발생하며, 이 때문에 Windows가 다시 시작됩니다. 최종 사용자는 이 문서에서 설명하는 핫픽스를 구해 이 문제를 해결할 수 있습니다. 소프트웨어 개발자는 매니페스트의 모든 속성에 단일 스키마만 존재하도록 하여 이 문제를 방지할 수 있습니다. 위의 예제에서 다음과 같은 태그를 사용하면 이 문제가 방지됩니다.
<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
Visual Studio 2005에서 만든 매니페스트가 이 문제를 나타낼 수 있습니다. 이 문제는 Visual Studio 2005 서비스 팩 1에서 업데이트된 Mt.exe 파일로 해결됩니다.


[MFC] CDockablePane

저장소/VC++
출처 :  http://knob.egloos.com/2780159


1. CFrameWndEx 상속 클래스에 다음과 같이 CDockablePane 객체를 선언하고.

CDockablePane m_Panes[5]; // 필요한 만큼의 갯수로 선언

2. CFrameWndEx 상속 클래스의 OnCreate()에 다음과 같은 부분들이 있는지 확인 한 후에,

// 메뉴 모음을 활성화해도 포커스가 이동하지 않게 합니다.
CMFCPopupMenu::SetForceMenuFocus(FALSE);
// 사용자 정의 도구 모음 작업을 허용합니다.
InitUserToolbars(NULL, uiFirstUserToolBarId, uiLastUserToolBarId);
// 도구 모음 및 도킹 창 메뉴 바꾸기를 활성화합니다.
EnablePaneMenu(TRUE, ID_VIEW_CUSTOMIZE, 0, ID_VIEW_TOOLBAR);
// Visual Studio 2005 스타일 도킹 창 동작을 활성화합니다.
CDockingManager::SetDockingMode(DT_SMART);
// Visual Studio 2005 스타일 도킹 창 자동 숨김 동작을 활성화합니다.
EnableAutoHidePanes(CBRS_ALIGN_ANY);
// Enable Docking
EnableDocking(CBRS_ALIGN_ANY);

3. 그 뒤에 아래와 같이 배치해 준다.

if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT

if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[1]); // BOTTOM
DockPane(&m_Panes[0]); // LEFT


if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT
DockPane(&m_Panes[1]); // BOTTOM
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT
DockPane(&m_Panes[1]); // LEFT
// 0번을 2번의 위에 위치 시킨다.
m_Panes[0].DockToWindow(&m_Panes[1], CBRS_TOP);
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT
DockPane(&m_Panes[1]); // LEFT
CDockablePane* pTabbedBar = NULL;
// Tab 형식으로 붙인다. 
m_Panes[1].AttachToTabWnd(&m_Panes[0], DM_SHOW, TRUE, &pTabbedBar);


if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[2].Create(_T("Pane 2"), this, CRect(0, 0, 200, 100), TRUE, 1002,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[2].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT
DockPane(&m_Panes[1]); // LEFT
DockPane(&m_Panes[2]); // LEFT
// 0번을 2번의 위에 위치 시킨다.
m_Panes[0].DockToWindow(&m_Panes[2], CBRS_TOP);
CDockablePane* pTabbedBar = NULL;
// 1을 0에 Tab 형식으로 붙인다. 
m_Panes[1].AttachToTabWnd(&m_Panes[0], DM_SHOW, TRUE, &pTabbedBar);
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // BOTTOM
DockPane(&m_Panes[1]); // BOTTOM
CDockablePane* pTabbedBar = NULL;
// 0번을 1번의 왼쪽에 위치 시킨다.
m_Panes[0].DockToWindow(&m_Panes[1], CBRS_LEFT);
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[2].Create(_T("Pane 2"), this, CRect(0, 0, 200, 100), TRUE, 1002,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[3].Create(_T("Pane 3"), this, CRect(0, 0, 200, 100), TRUE, 1003,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[4].Create(_T("Pane 4"), this, CRect(0, 0, 200, 100), TRUE, 1004,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[2].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[3].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[4].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // BOTTOM
DockPane(&m_Panes[1]); // BOTTOM
DockPane(&m_Panes[2]); // LEFT
DockPane(&m_Panes[3]); // LEFT
DockPane(&m_Panes[4]); // RIGHT
// 0번을 1번의 왼쪽에 위치 시킨다.
CDockablePane* pTabbedBar = NULL;
m_Panes[0].DockToWindow(&m_Panes[1], CBRS_LEFT);
// 3을 2에 Tab 형식으로 붙인다. 
m_Panes[3].AttachToTabWnd(&m_Panes[2], DM_SHOW, TRUE, &pTabbedBar);
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[2].Create(_T("Pane 2"), this, CRect(0, 0, 200, 100), TRUE, 1002,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[3].Create(_T("Pane 3"), this, CRect(0, 0, 200, 100), TRUE, 1003,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[4].Create(_T("Pane 4"), this, CRect(0, 0, 200, 100), TRUE, 1004,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[2].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[3].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[4].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // BOTTOM
DockPane(&m_Panes[1]); // BOTTOM
DockPane(&m_Panes[2]); // LEFT
DockPane(&m_Panes[3]); // LEFT
DockPane(&m_Panes[4]); // RIGHT
CDockablePane* pTabbedBar = NULL;
// 1을 0에 Tab 형식으로 붙인다
m_Panes[1].AttachToTabWnd(&m_Panes[0], DM_SHOW, TRUE, &pTabbedBar);
// 3을 2에 Tab 형식으로 붙인다. 
m_Panes[3].AttachToTabWnd(&m_Panes[2], DM_SHOW, TRUE, &pTabbedBar); 

[MFC] Application Layout State - 레이아웃 상태(저장) 관련 내용

저장소/VC++
출처 :  http://surfree.egloos.com/10681365 


MS VS 2008부터 MFC Feature Pack을 지원합니다.

Doc-View 형태의 응용프로그램을 만들면 MFC Feature Pack에서 제공하는 OutlookBar 와 Docking Pane를 이용할 수 있습니다.

OutlookBar와 Docking Pane의 레이아웃은 자동으로 저장되고 로드 됩니다.

매우 편리한 기능이긴 하지만 또한 매우 불편한 기능입니다.

물론 이 레이아웃 상태에 대해서 커스터마이징을 할 수 있는 여지를 두었군요.

MFC Feature Pack으로 Doc-VIew 응용프로그램을 생성할 시 기본 App 클래스는

CWinApp에서 CWinAppEx로 변경됩니다.

CWinAppEx에서 이 상태 저장 및 복구를 하는 군요.

CWinAppEx의 메소드 중 다음 메소드를 주의해서 보시면 됩니다.

CleanState(): 레이아웃 상태를 모두 초기화 한다.
LoadState(): 레이아웃 상태를 로드한다.
SaveState(): 레이아웃 상태를 저장한다.

위와 같은 메소드가 있지만 CleanState() 정도가 유용하게 쓰일 수 있을 것 같습니다.

CWinAppEx를 상속받은 클래스의 InitInstance()에서

SetRegistryKey() 구문 다음에 CleanState()를 호출하면 항상 레이아웃이 초기화한 상태로 표시되게 됩니다.

레이아웃을 로드하는 시점은 ProcessShellCommand()에서 프레임워크상 자동으로 로딩되게 되어 있습니다.

또한 이 레이아웃 자동 저장이 필요없다면

CWinAppEx의 다음 메소드를 오버라이딩 합니다.

virtual void OnClosingMainFrame(CFrameImpl* pFrameImpl);

기본 동작은 SaveState() 메소드를 호출합니다.

그러므로 레이아웃 자동저장이 되지 않게 하기 위해서는 OnClosingMainFrame()메소드를 오버라이딩하여 빈 구문으로 놓으면 레이아웃이 자동으로 저장되지 않습니다.