<응용 프로그램을 최소 크기 만들기>

MFC 4.0으로 두 프로그램 간의 메시지 전달 프로그램을 작성할 때 실행중이라는 것만 확인하면 됩니다. 그래서 프로그램을 최소크기로 작업줄에 띄우고 싶은데 어떻게 하면 되는지요.

 윈도우는 원래 크기로 복구할 때 WM_QUERYOPEN 메시지를 전달합니다. 클래스 위저드를 사용해 OnQueryOpen()에서 메시지를 처리한 후 응용 프로그램이 원래 크기로 복구하지 않게 하려면 FALSE를 리턴하면 됩니다.

BOOL CMainFrame::OnQueryOpen()
{
     ....
     return FALSE;
}

< 에디트 박스에서 엔터키 확인 방법 >

다이얼로그박스에 있는 에디트 박스에서 엔터키가 눌려질 때마다 데이터를 얻고 싶습니다.

 컨트롤이 생성되기 전에 메시지를 가로채서 작업하는 것을 슈퍼클래싱이라 하며, 컨트롤이 생성된 후에 메시지를 가로채는 것을 서브클래싱이라고 합니다. 그러므로 다이얼로그박스의 에디트 컨트롤에서 엔터키의 입력여부를 체크하고 싶다면 서브클래싱을 이용하면 됩니다.
 먼저 CEdit 클래스를 베이스 클래스로 선택한 후 CEditTest로 클래스명을 지정했다면 WM_CHAR 메시지를 선택합니다. CEditTest::OnChar()의 첫 번째 인자인 nChar가 에디트 컨트롤에 들어오는 문자이므로 제어하려는 문자를 써 주면 됩니다. 가령 숫자면 들어오길 바란다면 다음과 같이 하면 됩니다.

if((nChar >= '0' && nChar <= '9') || (nChar == VK_BACK))
// VK_BACK는 백스페이스이다.
{
     CEdit::OnChar( 내보낼 문자, 나머지 인자들... )
}
else
............  

 다음으로 다이얼로그 클래스가 존재하는 파일이 testDlg.cpp/h라면 testDlg.h에서 'CEditTest m_EditTest;' 라고 한 후 testDlg.h의 맨 앞부분에 '#include "EditTest.h"를 붙여주면 됩니다.
 이제 마지막으로 InitDialog()에서 'm_EditTest.SubclassDlgItem(IDC_EDITTEST, this); 를 첨가하면 에디트 컨트롤 서브클래싱은 끝납니다. 이와 같은 방법을 사용하면 에디트 컨트롤에 들어오는 문자를 모두 제어할 수 있습니다.
 다면 한 가지 주의할 점은 서브클래싱할 때 컨트롤 클래스 변수 정의 시 충돌이 생기므로 원하는 에디트 박스의 멤버변수를 클래스 위저드에서 설정하면 안됩니다.

 

<오버랩 이미지 표현하기>

하나의 배경 이미지에 여러 주제 이미지를 겹쳐 하나의 오버랩 이미지를 표현하고 싶습니다.

 겹쳐진 이미지를 사용하기 위해서는 먼저 그 이미지가 오버레이(overlay) 이미지로 정의돼 있어야 합니다. CImageList::SetOverlayImage()를 사용하면 이미지 리스트당 4개까지 비트맵을 오버레이 이미지로 정의할 수 있습니다.

     m_imageList.SetOverlayImage(0, 1);

 SetOverlayImage()는 이미지 인덱스와 오버레이 인덱스를 파라미터로 취하는데, 여기서 오버레이 인덱스는 1에서부터 시작한다는 것을 유의해야 합니다.

m_imageList.Draw(pDC, 3, ptOverlay, INDEXTOOVERLAYMASK | ILD_OVERLAYMASK);

이 때 INDEXTOOVERLAYMASK 매크로와 ILD_OVERLAYMASK 플래그 조합은 오버레이 이미지 인덱스가 기초 이미지와 조합되도록 하기 위한 것입니다.

 

<사용 가능한 시스템 메모리 용량>

비주얼 C++ 4.0에서 메모리를 할당하려고 남은 메모리 용량을 알고 싶은데 어떤 함수를 이용해야 하는지 알고 싶습니다.

 현재 사용가능한 메모리 용량을 알아보려면 GlobalMemoryStatus()를 사용하면 됩니다.
 GlobalMemoryStatus()는 현재 시스템 구성에서 프로그램이 실행될 수 있는지에 대한 정보를 프로그래머에게 제공합니다.
 이 함수를 사용하려면 전체 메모리에 대한 정보를 갖고 있는 구조체 (MEMORYSTATUS)의 주소를 전달해야 하며, 이 주소로 사용 가능한 물리 메모리와 가상 메모리를 얻을 수 있습니다.

 

<상태바 모양 변경>

상태바에 사용되는 폰트를 변경하려 합니다. 글꼴을 변경하는데 필요한 멤버함수가 CStatusBar에 존재하는지 알고 싶습니다.

 멤버 함수인 CWnd::SetFont를 사용하면 간단히 해결할 수 있습니다. CStatusBar는 CWnd 클래스에서 상속받은 것이므로 WM_SETFONT 메시지를 사용할 수 있습니다. 좀 더 예쁜 글꼴의 상태바를 만들려 한다면 상태바가 생성되고 출력되기 전에 CMainFrame::OnCreate 에서 3차원 스타일로 변경하면 됩니다.

 

<상태바에 작업진행 표시>

MFC 4.0으로 상태바에 작업 진행 과정이나 관련 자료를 나타나게 하고 싶습니다.

 상태바에 작업의 진행과정을 표시하는 방법은 여러 가지입니다. 그 중 하나로 CStatusBarBar에서 상속된 CMeterBar 클래스를 생성하는 방법이 있습니다. 여기서 상태바 영역을 다시 그리 필요가 있을 때마다 CStatusBar의 멤버 함수 DoPaint()를 호출하면 됩니다. 자세한 내용은 도움말을 참고하세요.
 또한 일반적인 상태바 영역을 측정영역(meter pane)으로 변환하려면 스타일을 SBPS_METER 로 설정해야 하는데, 이를 위해선 CStatusBar::SetPaneInfo 를 호출하면 됩니다.

 

<Doc 배열을 View에서 사용하는 방법>

도큐먼트 클래스에서 만든 배열인 a[i][j]를 뷰 클래스에서 읽어, a[i]는 x축, a[j]는 y축으로 하는 그래프를 그리려 합니다.

 뷰 클래스 안에서 GetDocument()를 사용해 도큐먼트를 지시하는 포인터를 구하면 문제를 간단히 해결할 수 있습니다.

(도큐먼트 클래스)* = GetDocument();
(도큐먼트 클래스)->a[i][j];

 

<창의 트래킹 크기 제한>

윈도우의 창의 크기와 트래킹(tracking) 크기를 화면의 1/4로 지정하고 싶습니다.

 윈도우는 최대 최소 트래킹 크기, 최대 창의 위치와 크기를 결정해야 할 때 WM_GETMAXMININFO 메시지를 전달합니다. 따라서 트래킹 크기를 제한하려면 OnGetMaxMinInfo()에서 다음과 같이 메시지를 처리하면 됩니다.

// 창의 크기와 트래킹 사이즈를 화면의 1/4로 제한한다.
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) {
     lpMMI->ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN)/2;
     lpMMI->ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN)/2;

     CMDIFrameWnd::OnGetMinMaxInfo(lpMMI);
}

 

<도큐먼트/뷰 구조>

도큐먼트에 뷰를 등록하려고 일단 뷰를 생성한 후 CDocument::AddView를 부르면 ASSERT에서 아직 제대로 된 윈도우가 아니라는 경고와 함께 실행이 멈춥니다. 그래서 우선 뷰를 Create로 만들고 호출하니 이번에는 제대로 등록은 됐지만 뷰가 아직도 도큐먼트에 연결되지 않았다는 경고를 내보냅니다.

 도큐먼트/뷰 아키텍처는 간단한 구조가 아니므로 단순히 연결한다고 해서 되는 건 아닙니다. 이 아키텍처에는 도큐먼트, 뷰 뿐만 아니라 프레임 윈도우까지 포함됩니다. 이 세 가지를 합쳐서 템플릿이라고 합니다.
 우선 애플리케이션이 실행되면 도큐먼트, 뷰, 프레임 윈도우가 합쳐져 템플릿을 생성한 후 연계시킵니다. 즉, 프레임 윈도우가 생성되고 도큐먼트가 생성된 후 뷰가 연결되는 것이죠.
 만약 도큐먼트, 뷰, 프레임 윈도우가 연결된 상태가 맘에 안든다면 템플릿 클래스를 새로 만드는 수밖에 없습니다.

 

<화면의 일부분을 비트맵으로>

화면에 출력된 그림의 일부분을 비트맵으로 분리시키려고 합니다. 터보 C의 경우 getimage()로 처리했는데, 비주얼 C++에서 이런 역할을 하는 API가 있는지 알고 싶습니다.

 비주얼 C++의 경우 화면을 분리해 비트맵을 만드는 함수가 따로 존재하지 않습니다. 하지만 GetDC, ReleaseDC, CreateDC, DeleteDC 함수로 윈도우의 핸들을 얻을 수 있으므로 이에 관련된 장치 컨텍스트에 접근해 화면을 분리하면 됩니다.
 BitBlt 함수를 사용해 화면 DC로부터 메모리에 있는 장치 컨텍스트로, 그런 다음에야 비트맵을 복사할 수 있습니다. 화면으로부터 비트맵 이미지를 캡처하거나 혹은 비트맵을 디스크에 저장하거나 출력할 때 팔레트 정보를 갖도록 하기 위해선 현재의 논리적 팔레트를 저장해야 합니다.

HDC hMemDC;
HBITMAP hBitmap;

hMemDC = CreateCompatibleDC(hDC);  // hDC는 분리해 낼 화면의 hDC
hBitmap = CreateCompatibleBitmap(hMemDC, nWidth, nHeight);
                                       // nWidth, nHeight는 비트맵의 크기
SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, nWidth, nHeight, hDC, SrcX, SrcY, SRCCOPY);
                                       // SrcX, SrcY는 비트맵의 시작 위치

....... // 저장

DeleteDC(hMemDC);
DeleteObject(hBitmap);    // 사용후 제거한다.     

 

<윈도우를 중앙에 위치>

MFC 4.0 프로그래밍할 때 상위 윈도우를 기준으로 하위 윈도우를 중앙에 위치시키고 싶습니다.

 MFC에서 제공하는 CWnd::CenterWindow를 호출하면 윈도우를 중앙에 위치시킬 수 있습니다. 만약 다른 윈도우를 기준으로 중앙에 위치시키고자 한다면 CWnd 형의 객체에 포인터를 전달하면 됩니다.

//상위 윈도우를 기준으로 중앙에 위치시킨다.
CenterWindow();

//윈도우를 전체 화면의 중앙에 위치시킨다.
CenterWindow(GetDesktopWindow());

//응용 프로그램의 메인 윈도우를 중앙에 위치시킨다.
AfxGetMainWnd()->CenterWindow();

 

<다른 프로그램을 실행할 땐 WinExec>

MFC 4.0으로 작성한 응용 프로그램에서 메뉴를 선택했을 때 노트패드가 실행되도록 하는 방법을 알고 싶습니다.

 비주얼 C++ 4.0 으로 짠 응용 프로그램에서 노트패드를 실행하려면 WinExec()를 사용하면 됩니다.
          ::WinExec(_T("notepad.exe", SW_SHOW));

여기서 SW_SHOW는 불려진 프로그램을 활성화하고자 할 때 사용하며, 만약 자신의 프로그램이 활성화된 채로 다른 프로그램을 부르고자 한다면 SW_SHOW 대신 SW_SHOWNA 를 쓰면 됩니다.
 참고로 특정 디렉토리에 있는 파일을 함께 열고 싶다면, 윈도우의 관련 특성을 통해 파일을 열거나 작업 디렉토리를 지정할 수 있는 ShellExecute()를 쓰면 됩니다.

//maso.txt를 연결된 응용프로그램으로 연다.
::ShellExecute(NULL, NULL, _T("maso.txt"),
           NULL, _T("c:\sally"), SW_SHOWMINIZED);
//응용프로그램을 최소화시켜
//실행 작업 디렉토리를 c:\sally 로 설정한다.