IT_Programming/MFC · API

메뉴 항목을 사용할 수 없게 하는 MFC 특성을 무효화하려면..

JJun ™ 2007. 12. 25. 13:45

<다이얼로그박스에 툴팁을 추가하려면>

 비주얼 C++ 5.0으로 만든 애플리케이션의 다이얼로그박스에 툴팁을 나타내고 싶습니다.  

 툴팁은 CToolTipCtrl 클래스를 이용하면 쉽게 구현할 수 있습니다. 먼저 Create()를 호출해서 툴팁 객체를 생성합니다. 그리고 나서 AddTool()를 호출해 각각의 컨트롤과 툴팁 문자열을 연결해 줍니다. 여기서 툴팁 문자열을 표시해 주는 함수는 ReplyEvent()이며, 툴팁 컨트롤 객체를 생성해 주고 컨트롤과 연결할 수 있는 가장 적당한 곳은 WM_INITDIALOG 메시지의 핸들러(OnInitDialog())입니다.
이렇게 툴팁을 초기화해 준 후에 ReplyEvent()를 호출하면 툴팁을 볼 수 있으며, 나머지 처리는 PreTranslateMessage()에서 담당합니다.

// 다이얼로그 박스에 버튼 2개와 에디트 박스 하나를 넣은 겁니다.
void CTooltipDlg::DoDataExchange(CDataExchange* pDX) {
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CTooltipDlg)
    DDX_Control(pDX, IDOK, m_btnOK);
    DDX_Control(pDX, IDCANCEL, m_btnCancel);
    DDX_Control(pDX, IDC_EDIT, m_edit);
    //}}AFX_DATA_MAP
}

BOOL CTooltipDlg::OnInitDialog() {
    CDialog::OnInitDialog();
    // 툴팁 컨트롤을 생성해 준다.
    m_tooltip.Create(this);
    // AddTool 함수에 컨트롤 객체의 포인터와 툴팁 문자열을 설정한다.
    m_tooltip.AddTool(&m_edit, "여기에 이름을 넣으세요");
    m_tooltip.AddTool(&m_btnOK, "여기를 누르면 확인입니다");
    m_tooltip.AddTool(&m_btnCancel, "여기를 누르면 취소입니다.");
    return TRUE;
}

BOOL CTooltipDlg::PreTranslateMessage(MSG* pMsg) {
    switch(pMsg->message)  {
    case WM_LBUTTONDOWN:            
    case WM_LBUTTONUP:              
    case WM_MOUSEMOVE:
        // 툴팁을 보여 준다.
        m_tooltip.RelayEvent(pMsg);
    }
    return CDialog::PreTranslateMessage(pMsg);

 

 

<메뉴 항목을 사용할 수 없게 하는 MFC 특성을 무효화하려면>

 CMenu::EnableMenuItem을 호출할 때 메뉴 항목이 사용할 수 없는 상태로 남아 있는데, 이 특성을 제거하고 싶습니다.  

 CFrameWnd::m_bAutoMenuEnable을 FALSE로 설정하면 됩니다. 이 데이터 멤버 함수가 TRUE이면 프레임웍은 on_UPATE_COMMAND_UI나 on_COMMAND 처리 함수를 갖지 않은 모든 메뉴 항목을 자동으로 사용할 수 없게 만들기 때문에 CMenu::EnableMenuItem을 호출할 때 메뉴 항목을 사용할 수 없습니다. 이 데이터 멤버는 초기값으로 TRUE를 갖지만 public 속성이므로 직접 변경할 수 있습니다.
 
m_bAutoMenuEnable = FALSE;
CMenu* pMenu = Getmenu();
pMenu->EnableMenuItem(ID_MENU_ITEM, MF_BYCOMMAND | MF_DISABLED);

 

 

<애플리케이션의 이전 위치를 보존하려면>

 애플리케이션을 종료할 때 애플리케이션의 크기와 위치를 기억해 두었다가 다음 실행 시 이전 위치와 같은 위치에서 애플리케이션을 실행하고 싶습니다.  

 애플리케이션의 셋팅을 저장하려면 윈도우 레지스트리를 이용하면 됩니다. 이를 지원하기 위해서 CWinApp 클래스는 SetRegistryKey()와 WriteProfileInt(), WriteProfileString(), GetProfileInt(), GetProfileString()을 제공합니다. SetRegistryKey()의 원형은 다음과 같습니다.

void SetRegistryKey(LPCTSTR lpszRegistryKey);

 일반적으로 lpszRegistryKey는 애플리케이션을 제작한 회사명입니다. 애플리케이션 위저드를 이용해 코드를 생성했다면 기본적으로 다음과 같이 코딩됩니다.

BOOL CAboutApp::InitInstance() {
    // 생략...
    // Change the registry key under which our settings are stored.
    // You should modify this string to be something appropriate
    // such as the name of your company or organization.

    SetRegistryKey(_T("Local AppWizard-Generated Applications"));
    // 생략...
}

 이 함수를 호출하면 자동으로 MRU(Most Recently Used) List가 저장됩니다.

레지스트리에 저장되는 형식은 다음과 같습니다.

HKEY_CURRENT_USER\Software\<company name>\
<application name>\<section name>\<value name>

 애플리케이션이 위치와 크기를 보관하고 애플리케이션 시작 시 보관된 애플리케이션의 크기와 위치를 읽어오는 작업을 하기에 가장 좋은 부분은 CMainFrame의 onClose()와 onShowWindow()입니다.
 다음 예는 CFameWnd의 onClose()와 onShowWindow()를 오버라이드한 것으로 애플리케이션의 크기와 위치를 기억해 둡니다.

 

void CMainFrame::OnClose() {
    // 현재 메인 윈도우의 위치 정보를 얻어온다.
    WINDOWPLACEMENT wp;
    GetWindowPlacement(&wp);
    // 현재 메인 윈도우의 위치와 크기를 레지스트리에 쓴다.
    AfxGetApp()->WriteProfileInt("Initialization",
        "VertPos",
        wp.rcNormalPosition.top);
    AfxGetApp()->WriteProfileInt("Initialization",
        "HorizPos",
        wp.rcNormalPosition.left);
    AfxGetApp()->WriteProfileInt("Initialization",
        "Height",
        wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
    AfxGetApp()->WriteProfileInt("Initialization",
        "Width",
        wp.rcNormalPosition.right - wp.rcNormalPosition.left);
    CFrameWnd::OnClose();
}

void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus) {       
    CFrameWnd::OnShowWindow(bShow, nStatus);
    // 레지스트리에서 이전에 저장된 프레임 윈도우의 크기와 위치를
    // 얻어 와서 프레임 윈도우의 크기를 조정한다.

    int iVert =
        AfxGetApp()->GetProfileInt("Initialization","VertPos",0);
    int iHoriz =
        AfxGetApp()->GetProfileInt("Initialization","HorizPos",0);
    int Width =
        AfxGetApp()->GetProfileInt("Initialization","Width",400);;
    int Height =
        AfxGetApp()->GetProfileInt("Initialization","Height",280);
    // adjust the application's frame size and position
    SetWindowPos(NULL,iHoriz,iVert,Width,Height, NULL);
}

 

<시스템 메뉴를 없애려면>

 비주얼 C++에서 타이틀바에 있는 아이콘 팝업 메뉴를 제거하려 합니다.  

 타이틀바에 있는 시스템 메뉴를 없애려면 CFrameWnd 클래스에서 상속받은
CMainFrame에 있는 PreCreateWindow()에 다음과 같이 한 줄을 추가하면
간단히 제거할 수 있습니다.

cs.style &= ~WS_SYSMENU;

보통 윈도우 스타일인 WS_OVERLAPPEDWINDOW에는 시스템 메뉴와 여러
윈도우 스타일이 정의돼 있기 때문에 기본값에서 시스템 메뉴를 없애면 되는
거죠.