IT_Programming/MFC · API

툴바 숨기기/보이기 옵션 주기 / 클라이언트 영역을 클릭해 윈도우를 이동

JJun ™ 2007. 12. 25. 12:17
LONG

<최대화된 SDI 윈도우를 실행하려면>

 처음 윈도우를 실행할 때 최대화(Maximize)된 상태로 실행하려면 어떻게 해야 하는지 알고 싶습니다. MDI의 경우는 위저드에서 옵션을 설정하면 되지만 SDI의 경우는 위저드에서 옵션을 설정해도 최대화되지 않습니다.  

CWinApp의 InitInstance 함수에서 다음과 같이 코드를 변경해 주면 가능합니다.

 

// 원래 코드
BOOL CMailApp::InitInstance() {
.    m_pMainWnd->ShowWindow(SW_SHOW);
     m_pMainWnd->UpdateWindow();
     return TRUE;
}

// 바뀐 코드
BOOL CMailApp::InitInstance() {
.    m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
     m_pMainWnd->UpdateWindow();
     return TRUE;
}

 

<DC 핸들로 CDC 객체를 만들려면>

오너 드로우(owner draw) 버튼을 만들 때 WM_DRAWITEM 메시지에서는 DRAWITEMSTRUCT 구조체와 DC 핸들을 넘기는데, 이를 이용해 CDC 객체를 생성하고

싶습니다.

CDC의 멤버 함수중 FormHandle()이라는 멤버 함수가 있습니다. 핸들을 가지고 객체를 생성할 수 있게 하는 함수로 핸들만 알고 있으면 객체를 생성할 수 있습니다. FromHandle()은 CDC 뿐만 아니라 핸들을 갖고 있는 윈도우 오브젝트에 모두 사용할 수 있습니다.
예를 들면 CFont나 CBrush와 같은 GDI 객체나 CWnd, CSocket을 비롯한 핸들을 이용하는 객체는 모두 이런 멤버 함수를 갖고 있으므로 핸들을 알고 있으면 언제든지 객체를 구성할 수 있습니다.
다음 코드는 DC 핸들을 이용해 CDC 객체를 생성하는 예를 보여 주는 코드입니다.

 

void MyODList::DrawItem(LPDRAWITEMSTRUCT lpDrawItem) {
    CDC* pDC;
    pDC = CDC:FromHandle(lpDrawItem->hDC);
}

 

<트리 컨트롤을 이용한 애플리케이션 만들기>

CTreeView를 이용해 애플리케이션을 작성하려고 합니다. 그런데 제가 직접 정의한 트리 컨트롤을 이용하고 싶습니다.  

먼저 CTreeCtrl로부터 상속받은 클래스를 작성합니다. 그리고 나서 CTreeView의 GetTreeCtrl()를

이용해 CTreeView로부터 트리 컨트롤을 얻어 옵니다.
다음은 얻어온 트리 컨트롤을 자신이 제작한 트리 컨트롤로 서브클래싱하는 것입니다.

그러면 트리뷰에서 사용자가 정의한 트리 컨트롤을 사용할 수 있습니다.

 

// 먼저 컨트롤을 작성한다.
class CYourTreeCtrl : public CTreeCtrl {
// 여기에 작성.
};

 

// 트리뷰에 자신이 작성한 트리 컨트롤을 멤버로 선언한다.
Class CYourTreeView : public CTreeView {
protected: CYourTreeCtrl m_yourTreeCtrl;
.};

 

// onCreate 핸들러에서 자신이 제작한 컨트롤로 서브클래싱한다.
void  CYourTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) {
    if(CTreeView::OnCreate(plCreateStruct) != 0)
        return 1;
    if(!m_yourTreeCtrl.SubclassWindow(GetTreeCtrl().GetSafeHwnd()))
        return 1;
    return 0;
}

 

<기본 브라우저를 띄우려면>

 프로그램 안에서 시스템에 설정돼 있는 기본 브라우저를 띄우는 방법을 알고 싶습니다.  

윈도우 API중에서 ShellExecute()를 이용하면 간단히 해결할 수 있습니다.
함수의 원형은 다음과 같습니다.

HINSTANCE ShellExecute( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile,
       LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd);

ShellExecute()의 세번째 인자인 plFile에 URL을 적어주면 시스템에 설정돼
있는 기본 브라우저를 실행해 지정한 URL을 열어 줍니다.

ShellExcute(NULL, NULL, http://www.somesite.com, NULL, SW_SHOWNORMAL);

 

<도큐먼트 없는 애플리케이션 만들기>

 MFC로 도큐먼트나 뷰가 없는 애플리케이션을 만들고 싶습니다.  

 두 가지 방법이 있는데, 하나는 위저드에서 다이얼로그 베이스(dialog based) 옵션을 선택하는 것입니다. 다이얼로그 베이스의 애플리케이션은 도큐먼트나 뷰가 생성되지 않습니다. 다른 한 가지는 CWinApp와 CFrameWnd를 직접 작성하는 것입니다. MFC 애플리케이션은 반드시 CWinApp와 CFrameWnd가 존재해야 하기 때문입니다.
 이렇게 위저드를 이용하지 않고 작성하면 CFramewnd에서 WM_PAINT 등의 일반적으로 윈도우가 처리하는 메시지를 처리해 주어야 합니다. 다음 예는 MFC 샘플에서 발췌한 내용으로 다음과 같이 작성하면 도큐먼트와 뷰가 없는 윈도우를 생성할 수 있습니다.

(참고 : VC++ 6.0 에는 따로 이러한 기능을 제공합니다.)

 

#include <afxwin.h>
class CNoviewWindow : public CFrameWnd {
public:
    CNoviewWindow() {
    Create(NULL, _T("Hello World!"), WS_OVERLAPPEDWINDOW, rectDefault); }
};

class CNoviewApp : public CWinApp {
public:
    virtual BOOL InitInstance();
};

BOOL CNoviewApp::InitInstance() {
    m_pMainWnd = new CNoviewWindow();
    m_pMainWnd->ShowWindow(m_nCmdShow);
    m_pMainWnd->UpdateWindow();
    return TRUE;
}
CNoviewApp NoviewApp;

ARTICLE

<툴바 숨기기/보이기 옵션 주기>

MFC로 작성한 애플리케이션에서 툴바와 상태바는 기본으로 추가되는데, 메뉴의 보기 항목에 툴바를 숨길 수 있는 옵션이 있습니다. 이렇게 툴바를 숨기거나 보이게 선택 옵션을 주는 방법이 있나요?

물론 있습니다. 프로그램으로 툴바(또는 상태바)를 숨기거나 보이게 하려면 메인프레임에 이 메시지를 보내면 간단히 해결할 수 있습니다. 보기 메뉴에서 툴바를 보이기/숨기기 명령은 메인프레임이 이를 대신 처리하므로 메인프레임에는 기본적으로 이 명령에 대한 핸들러가 작성돼 있습니다. 이때 wParam값이 0이면 숨기고, 0이 아니면 다시 보여 줍니다. 여기서 툴바나 상태바를 없애거나 다시 보이게 하는 메뉴 명령 ID는 ID_VIEW_TOOLBAR와 ID_VIEW_STATUSBAR입니다.

다음의 소스는 툴바와 상태바를 숨기는 코드입니다. 반대로 툴바나 상태바를 보이게 하려면 wParam값을 0이 아닌 값을 넣어 주면 됩니다.

 

if( ((CMainFrame*)GetParent())->m_wndToolBar.IsWindowVisible()) {
        GetParent()->SendMessage(WM_COMMAND, ID_VIEW_TOOLBAR, 0L);
}

if( ((CMainFrame*)GetParent())->m_wndStatusBar.IsWindowVisible()) {
        GetParent()->SendMessage(WM_COMMAND, ID_VIEW_STATUS_BAR, 0L);
}

 

<클라이언트 영역을 클릭해 윈도우를 이동하려면>

캡션 뿐 아니라 윈도우의 다른 곳을 클릭했을 때도 윈도우를 이동시킬 수 있는 프로그램을

작성하고 싶습니다.  

윈도우는 마우스 위치를 결정할 필요가 있을 때 WM_NCHITTEST 메시지를 윈도우에 전달합니다. 그러므로 마우스가 캡션에 위치하지 않았더라도 윈도우를 속일 수 있습니다.
 방법은 먼저 위저드를 사용해 WM_NCHITTEST 메시지를 처리하고, 기본 클래스 함수를 호출합니다. 함수가 HTCLINE를 반환한 후 마우스가 클라이언트 영역에 있다고 알려 줄 때 마우스 위치를 캡션으로 인식하게끔 HTCATION값을 돌려주면 됩니다.

UNIT CSampleDialog::OnNchitTest(CPoint point) {
   UINT nHiTest = CDialog::OnNchitTest(point);
   return (nHitest ==HTCLINT) ? HTCAPTION : nHitest
}

 그 다음에 클래스 위저드를 사용해 뷰에서 WM_LBUTTONDOWN 메시지를 처리하고, 프레임 윈도우에 마우스의 눌림 상태를 HTCATION로 지정해 WM_NCLBUTTONDOWN 메시지를 전달하면 됩니다.

void CSampleView::OnLBottonDown(UNIT nFlags, CPoint point) {
   CView;;OnLBottonDown(nFlags, point) ;
   
//사용자가 캡션을 클릭한 것으로 인식하게 프레임을 속인다.
   GetParent()->PostMessage(WM_ NCLBUTTONDOWN, HTCATION)
   MAKELPARAM(point.x, point.y) ;
}

여기서 Cwnd::Getparent에 대한 호출은 필요하지 않습니다.

void CSampleDialog::OnLBottonDown(UNIT nFlags, CPoint point) {
   CDialog::OnLBottonDown(nFlags, point)
   
//사용자가 캡션을 클릭한 것으로 인식하게끔 대화상자를 속인다.
   PostMessage(WM_ NCLBUTTONDOWN, HTCAPTION,
                MAKELPARAM(point.x, point.y));
}

 하지만 이 방법은 두 가지 문제점이 있습니다. 하나는 클라이언트 영역을 더블클릭하면 윈도우가 최대화돼야 하는데, 뷰를 가지는 프레임 윈도우에서는 허용하지 않는다는 것이고, 또다른 하나는 왼쪽 마우스 단추를 클릭할 때 캡션바를 클릭한 것처럼 인식된다는 것입니다.

 

 

[↓Click! 최대화된 SDI 윈도우를 실행하려면 / DC 핸들로 CDC 객체를 만들려면 /

             트리 컨트롤을 이용한 애플리케이션 만들기 / 기본 브라우저를 띄우려면 /

             도큐먼트 없는 애플리케이션 만들기]