<스플리터 윈도우의 크기를 고정하려면>

MFC 클래스 위저드로 스태틱 스플리터(Static splitter) 윈도우를 이용해 하나의 프레임에 두 개의 뷰를 갖고 있는 예제를 작성했습니다. 스플리터 윈도우에서 크기 변경이 불가능하도록 만들려면 어떻게 해야 하나요.

스플리터 윈도우에서 크기 변경이 안되도록 하려면 우선 스플릿바의 행동 양식에서 그 방법을 찾을 수 있습니다. 스플릿바는 WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK 메시지가 넘어 올 때 크기를 조정하도록 설계돼 있습니다. 그러므로 마우스가 스플릿바 위에 오면 마우스 커서가 변하게 되고 스플릿바 위에서 마우스를 누르면 그때부터 크기를 변경할 수 있게 됩니다. 그리고 눌렀던 마우스를 놓으면 크기 변경을 완료되는 거죠. 따라서 이 네 가지 메시지가 넘어올 때 아무 일도 하지 않도록 하면 됩니다. 즉, 메시지 핸들러를 아무 일도 하지 않도록 작성해 주면 처음 정해진 크기로 고정됩니다. 마우스가 스플릿바 위로 가도 커서가 변하지 않는 것은 물론이고 스플릿바 위를 클릭해도 크기가 조정되지 않습니다. 다음 코드를 참고하세요.

  헤더 파일
class CFixedSplitterWnd : public CSplitterWnd {
//. . .
protected:
    //{{AFX_MSG(CFixedSplitterWnd)
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
   //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

  소스 파일
//. . .
BEGIN_MESSAGE_MAP(CFixedSplitterWnd, CSplitterWnd)
    //{{AFX_MSG_MAP(CFixedSplitterWnd)
    ON_WM_MOUSEMOVE()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_LBUTTONDBLCLK()
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////
//CFixedSplitterWnd message handlers
void CFixedSplitterWnd::OnMouseMove(UINT nFlags, CPoint point) {
    // TODO:
    // 기본적으로 정의된 함수는 CSplitterWnd::OnMOuseMove(nFlag, point)이다.
    CWnd::OnMouseMove(nFlags, point); // 아무 일도 하지 않는다.
}

void CFixedSplitterWnd::OnLButtonDown(UINT nFlags, CPoint point) {
    // TODO:
    CWnd::OnLButtonDown(nFlags, point);
}

void CFixedSplitterWnd::OnLButtonUp(UINT nFlags, CPoint point) {
    // TODO:
    CWnd::OnLButtonUp(nFlags, point);
}

void CFixedSplitterWnd::OnLButtonDblClk(UINT nFlags, CPoint point) {
    // TODO:
    CWnd::OnLButtonDblClk(nFlags, point);
}

 

<다이얼로그 폰트를 변경하려면>

다이얼로그에 포함돼 있는 컨트롤의 폰트를 사용자 정의 폰트로 바꾸고 싶습니다.

다이얼로그에 포함되는 컨트롤은 기본적으로 다이얼로그의 폰트를 그대로 쓰게 됩니다. CFont 객체를 이용해 폰트를 생성한 후 컨트롤의 SetFont()를 호출하면 쉽게 컨트롤의 폰트를 변경할 수 있습니다. 이러한 동작을 취하기 가장 좋은 부분이 다이얼로그의 OnInitDialog()입니다. 다음을 참고하세요.

// ...
void CAboutDlg::DoDataExchange(CDataExchange* pDX) {
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CAboutDlg)
    DDX_Control(pDX, IDOK, m_button);
//}}AFX_DATA_MAP
}
// ...
BOOL CSomeDlg::OnInitDialog() {
    CDialog::OnInitDialog();
    m_font.CreateFont( // m_font는 이 클래스의 멤버로 선언돼 있다고 가정
        10, // nHeight
         8, // nWidth
         0, // nEscapement
         0, // nOrientation
         0, // nWeight
         0, // bItalic
         0, // bUnderline
         0, // cStrikeOut
         0, // nCharSet
         OUT_DEFAULT_PRECIS, // nOutPrecision
         0, // nClipPrecision
         DEFAULT_QUALITY, // nQuality
         DEFAULT_PITCH | FF_DONTCARE, // nPitchAnd

Family
         "Fixedsys" // lpszFacename
    );
    m_button.SetFont(&m_font, TRUE);
    return TRUE;
}
// ...

 

<MDI 프로그램 시작 시 차일드 윈도우를 띄우지 않으려면>

MDI로 프로그램을 하나 만들면 프로그램 시작시 항상 차일드 윈도우가 나타납니다. 프로그램 시작시 차일드 윈도우가 나타나지 않도록 할 수는 없는지요.

MFC 애플리케이션 위저드는 MDI를 생성할 때 자동적으로 차일드 윈도우가 나타나도록 설계돼 있습니다. 이것은 CSomeApp(CWinApp의 자식 클래스)의 InitInstance()에서 정의돼 있기 때문입니다. 애플리케이션 위저드가 만들어 준 InitInstance()를 살펴 보면 다음과 같은 코드를 찾아 볼 수 있습니다.

BOOL CSomeApp::InitInstance() {
    // ...
    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);
    if(!ProcessShellCommand(cmdInfo))
        return FALSE;
    //...
}

앞 코드에서 볼 수 있는 CCommandLineInfo 클래스는 명령어 라인에서 입력된 쉘 명령어(일반적으로 오픈할 파일이름)에 관한 정보를 포함하고 있으므로 쉘 명령어가 없으면 새로운 빈 도큐먼트를 생성해 보여 주게 됩니다. 따라서 다음과 같이 코드를 변경해 주면 빈 도큐먼트를 생성해 보여 주는 것을
강제적으로 막을 수 있습니다.

BOOL CSomeApp::InitInstance() {
    // ...
    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);
    cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
    if(!ProcessShellCommand(cmdInfo))
        return FALSE;
    // ...
}

여기서 CCommandLineInfo의 멤버 변수인 m_nShellCommand가 가질 수 있는 값은 다음과 같습니다.

enum{
    FileNew,
    FileOpen,
    FilePrint,
    FilePrintTo,
    FileDDE,
    FileNothing = -1
};

이중 FileNothing이 MDI 애플리케이션이 생성될 때 새로운 도큐먼트를 생성해 주는 것을 막아 주는 값입니다.

 

<프로퍼티 시트에 공통 다이얼로그 박스를>

프로퍼티 시트 안에 공통 다이얼로그박스(예를 들면 글꼴 다이얼로그 박스나 색 선택 다이얼로그박스 등)를 넣을 수 있는지 궁금합니다. 만약 넣을 수 있다면 어떻게 구현하는지도 알고 싶습니다.

아쉽게도 프로퍼티 시트 안에 공통 다이얼로그 박스는 넣을 수 없습니다. 공통 다이얼로그 박스는 모달 다이얼로그입니다. 그러나 프로퍼티 시트의 페이지는 모달로 동작하지 않으므로 프로퍼티 시트에 공통 다이얼로그를 넣을 수는 없습니다. 단, EnumFontFamilies()와 EnumFontFaces() 등의 API함수를
이용해서 공통 다이얼로그와 같은 기능을 하는 페이지는 만들 수 있습니다.

 

<캡션바에 애플리케이션 이름만 표시하려면>

MFC로 작성한 애플리케이션의 메인 윈도우의 캡션바에는 항상 애플리케이션 이름과 함께 Untitled 또는 파일 이름이 추가되는데, 그냥 애플리케이션의 이름만 캡션바에 나타나게 하려 합니다.

CMainFrame의 PreCreateWindow()를 다음과 같이 오버라이드하면 간단히 해결할 수 있습니다.

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) {
    // TODO:
    // CREATESTRUCT cs
    cs.style &= ~FWS_ADDTOTITLE ;
    return CFrameWnd::PreCreateWindow(cs);
}