[MFC] MainFrame 제목표시줄, 메뉴, 툴바, 크기고정

빵욱·2025년 1월 13일
post-thumbnail

MFC SDI기준으로 진행.

MainFrame의 제목표시줄, 메뉴, 툴바를 제거하고 크기도 고정시키고 싶어서 이것 저것 찾아보고 해보다 정리.

제목 표시줄 제거.

LoadFrame함수를 재정의

// in header file
virtual BOOL LoadFrame(UINT nIDResource, DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, CWnd* pParentWnd = NULL, CCreateContext* pContext = NULL);

클래스뷰에서 MainFrame 속성에서 추가하면 편함.


BOOL CMainFrame::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext)
{
	if (!CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext))
		return FALSE;

	// 제목 표시줄 제거
	ModifyStyle(WS_CAPTION, 0, SWP_FRAMECHANGED);
	// WS_CAPTION옵션을 제거하고 SWP_FRAMECHANGED:다시 그린다.

	return TRUE;
}

이 처럼 LoadFrame에서 해도되고,

기본적으로 생성되는 OnCreate 에서 해도 된다.

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	// 여기서 제거해도 가능.
	// ModifyStyle(WS_CAPTION, 0, SWP_FRAMECHANGED);

	return 0;
}

찾아보니 PreCreateWindow에서 하라는 자료도 봤는데 PreCreateWindow하면 적용이 안됬다.
PreCreateWindow 실행 이후에 OnCreate 또는 다른 Create과정에서 WS_CAPTION 스타일을 기본적으로 다시 적용하거나, 특정 조건에 따라 스타일을 재설정할 수 있다고 하는데 정확한 메커니즘은 찾아봐야겠다...
(잘 나오지도 않는다..)

메뉴, 툴바

메뉴와 툴바는 기본적으로 생성되는 관련 코드들은 제거한 후

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: CREATESTRUCT cs를 수정하여 여기에서
	//  Window 클래스 또는 스타일을 수정합니다.

	cs.hMenu = nullptr;

	return TRUE;
}

cs.hMenu = nullptr; 를 해서 제거했다.
이건 잘 동작한다.

위치고정

OnGetMinMaxInfo 메시지 함수를 추가했다.
ON_WM_GETMINMAXINFO 메시지에 대한 처리 함수다.
윈도우의 크기가 변경됬을 때 윈도우에 전달되는 메시지라 한다.

void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
	// 고정 크기 지정 (예: 800x600)
	lpMMI->ptMinTrackSize.x = 800; // 최소 가로 크기
	lpMMI->ptMinTrackSize.y = 600; // 최소 세로 크기
	lpMMI->ptMaxTrackSize.x = 800; // 최대 가로 크기
	lpMMI->ptMaxTrackSize.y = 600; // 최대 세로 크기

	CFrameWnd::OnGetMinMaxInfo(lpMMI);
}

크기 조절 못하게 + 시작 위치 고정.

윈도우 경계선에 마우스를 올리면 크기를 조절할 수 있는 그 동작을 막는거다.

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: CREATESTRUCT cs를 수정하여 여기에서
	//  Window 클래스 또는 스타일을 수정합니다.

	cs.style &= ~WS_THICKFRAME; // 크기 조절 제거.
	cs.hMenu = nullptr;

	cs.x = 0; // X 좌표
	cs.y = 0; // Y 좌표
	return TRUE;
}

PreCreateWindow에서 진행.
WS_THICKFRAME 스타일을 제거하면 된다고 한다.
위치 조정은 cs.x, cs.y를 0으로 고정했다.(모니터 왼쪽 상단 모서리)

모니터 해상도가 변경되도 크기 고정

모니터 해상도가 변경되면 Windows는 WM_DISPLAYCHANGE 메시지를 브로드캐스트한다고 한다.

// cpp file
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    // ... 기존 메시지 맵
    ON_WM_DISPLAYCHANGE()
END_MESSAGE_MAP()

메시지맵에 ON_WM_DISPLAYCHANGE를 추가한다.

void CMainFrame::OnDisplayChange(UINT nBitsPerPixel, int cxScreen, int cyScreen)
{
	// 현재 창의 위치와 크기 가져오기
	CRect rectWindow;
	GetWindowRect(&rectWindow);

	// 새 해상도 내에서 창의 위치 조정
	if (rectWindow.right > cxScreen || rectWindow.bottom > cyScreen)
	{
		int width = rectWindow.Width();
		int height = rectWindow.Height();

		// 창을 화면 왼쪽 상단으로 이동 (필요시 수정 가능)
		SetWindowPos(NULL, 0, 0, width, height, SWP_NOZORDER | SWP_NOACTIVATE);
	}
}

그리고 메시지 처리함수를 위와 같이 작성했다.
되는거 같긴한데 잘 되는지는 잘...
그리고 OnDisplayChange는 클래스 속성에서 찾아볼 수 없다.그래서 수동으로 추가했다.

GPT한테 물어보니
"ON_WM_DISPLAYCHANGE는 수동으로 추가해야 하며, Visual Studio의 메시지 처리 마법사에서 기본적으로 보이지 않을 수 있습니다. "
라고 한다..

https://learn.microsoft.com/en-us/windows/win32/gdi/wm-displaychange
이 문서에도 딱히 도움되는 정보는 없다..

profile
rove drink eat

0개의 댓글