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
이 문서에도 딱히 도움되는 정보는 없다..