다음을 통해 공유


창 기능

이 개요에서는 창 유형, 상태, 크기 및 위치와 같은 창의 기능에 대해 설명합니다.

창 유형

이 섹션에는 창 형식을 설명하는 다음 topics 포함되어 있습니다.

겹치는 Windows

겹치는 창은 제목 표시줄, 테두리 및 클라이언트 영역이 있는 최상위 창(자식이 아닌 창)입니다. 애플리케이션의 기본 창으로 사용할 수 있습니다. 창 메뉴, 최소화 및 최대화 단추 및 스크롤 막대가 있을 수도 있습니다. 기본 창으로 사용되는 겹치는 창에는 일반적으로 이러한 모든 구성 요소가 포함됩니다.

CreateWindowEx 함수에서 WS_OVERLAPPED 또는 WS_OVERLAPPEDWINDOW 스타일을 지정하면 애플리케이션이 겹치는 창을 만듭니다. WS_OVERLAPPED 스타일을 사용하는 경우 창에 제목 표시줄과 테두리가 있습니다. WS_OVERLAPPEDWINDOW 스타일을 사용하는 경우 창에 제목 표시줄, 크기 조정 테두리, 창 메뉴, 최소화 및 최대화 단추가 있습니다.

팝업 Windows

팝업 창은 애플리케이션의 기본 창 외부에 표시되는 대화 상자, 메시지 상자 및 기타 임시 창에 사용되는 특수 유형의 겹침 창입니다. 제목 표시줄은 팝업 창에 선택 사항입니다. 그렇지 않으면 팝업 창이 WS_OVERLAPPED 스타일의 겹치는 창과 동일합니다.

CreateWindowEx에서 WS_POPUP 스타일을 지정하여 팝업 창을 만듭니다. 제목 표시줄을 포함하려면 WS_CAPTION 스타일을 지정합니다. WS_POPUPWINDOW 스타일을 사용하여 테두리와 창 메뉴가 있는 팝업 창을 만듭니다. 창 메뉴를 표시하려면 WS_CAPTION 스타일을 WS_POPUPWINDOW 스타일과 결합해야 합니다.

자식 창

자식 창에는 WS_CHILD 스타일이 있으며 부모 창의 클라이언트 영역으로 제한됩니다. 애플리케이션은 일반적으로 자식 창을 사용하여 부모 창의 클라이언트 영역을 기능 영역으로 나눕니다. CreateWindowEx 함수에서 WS_CHILD 스타일을 지정하여 자식 창을 만듭니다.

자식 창에는 부모 창이 있어야 합니다. 부모 창은 겹치는 창, 팝업 창 또는 다른 자식 창일 수 있습니다. CreateWindowEx를 호출할 때 부모 창을 지정합니다. CreateWindowEx에서 WS_CHILD 스타일을 지정하지만 부모 창을 지정하지 않으면 시스템에서 창을 만들지 않습니다.

자식 창에는 클라이언트 영역이 있지만 명시적으로 요청되지 않는 한 다른 기능은 없습니다. 애플리케이션은 제목 표시줄, 창 메뉴, 최소화 및 최대화 단추, 테두리 및 자식 창에 대한 스크롤 막대를 요청할 수 있지만 자식 창에는 메뉴가 없습니다. 애플리케이션이 자식의 창 클래스를 등록하거나 자식 창을 만들 때 메뉴 핸들을 지정하면 메뉴 핸들이 무시됩니다. 테두리 스타일을 지정하지 않으면 시스템에서 테두리 없는 창을 만듭니다. 애플리케이션은 테두리 없는 자식 창을 사용하여 부모 창의 클라이언트 영역을 분할하는 동시에 분할을 사용자에게 보이지 않게 할 수 있습니다.

이 섹션에서는 자식 창의 다음과 같은 측면에 대해 설명합니다.

위치 지정

시스템은 항상 부모 창의 클라이언트 영역의 왼쪽 위 모서리를 기준으로 자식 창을 배치합니다. 자식 창의 어떤 부분도 부모 창의 테두리 밖에 나타나지 않습니다. 애플리케이션이 부모 창보다 큰 자식 창을 만들거나 자식 창의 일부 또는 전부가 부모의 테두리를 넘어 확장되도록 자식 창을 배치하는 경우 시스템은 자식 창을 클리핑합니다. 즉, 부모 창의 클라이언트 영역 외부 부분이 표시되지 않습니다. 부모 창에 영향을 주는 작업은 다음과 같이 자식 창에도 영향을 줄 수 있습니다.

부모 창 자식 창
제거됨 부모 창이 제거되기 전에 제거됩니다.
숨김 부모 창이 숨겨지기 전에 숨겨집니다. 자식 창은 부모 창이 표시되는 경우에만 표시됩니다.
이동됨 부모 창의 클라이언트 영역을 사용하여 이동했습니다. 자식 창은 이동 후 클라이언트 영역을 그리는 작업을 담당합니다.
표시 부모 창이 표시된 후에 표시됩니다.

 

클리핑

시스템은 부모 창의 클라이언트 영역에서 자식 창을 자동으로 클리핑하지 않습니다. 즉, 자식 창과 동일한 위치에 그리기를 수행하는 경우 부모 창이 자식 창 위에 그려짐을 의미합니다. 그러나 부모 창에 WS_CLIPCHILDREN 스타일이 있는 경우 시스템은 부모 창의 클라이언트 영역에서 자식 창을 클리핑합니다. 자식 창이 잘리면 부모 창이 자식 창 위에 그릴 수 없습니다.

자식 창은 동일한 클라이언트 영역의 다른 자식 창과 겹칠 수 있습니다. 하나 이상의 다른 자식 창과 동일한 부모 창을 공유하는 자식 창을 형제 창이라고 합니다. 자식 창 중 하나에 WS_CLIPSIBLINGS 스타일이 없는 한 형제 창은 서로의 클라이언트 영역에 그릴 수 있습니다. 자식 창에 이 스타일이 있는 경우 자식 창 내에 있는 형제 창의 일부가 잘립니다.

창에 WS_CLIPCHILDREN 또는 WS_CLIPSIBLINGS 스타일이 있는 경우 약간의 성능 손실이 발생합니다. 각 창은 시스템 리소스를 차지하므로 애플리케이션은 자식 창을 무차별적으로 사용하지 않아야 합니다. 최상의 성능을 위해 기본 창을 논리적으로 나누어야 하는 애플리케이션은 자식 창을 사용하는 대신 기본 창의 창 프로시저에서 이 작업을 수행해야 합니다.

부모 창과의 관계

애플리케이션은 SetParent 함수를 호출하여 기존 자식 창의 부모 창을 변경할 수 있습니다. 이 경우 시스템은 이전 부모 창의 클라이언트 영역에서 자식 창을 제거하고 새 부모 창의 클라이언트 영역으로 이동합니다. SetParentNULL 핸들을 지정하면 바탕 화면 창이 새 부모 창이 됩니다. 이 경우 자식 창은 바탕 화면에 그려지고 다른 창의 테두리 바깥쪽에 그려집니다. GetParent 함수는 자식 창의 부모 창에 대한 핸들을 검색합니다.

부모 창은 클라이언트 영역의 일부를 자식 창에 포기하며 자식 창은 이 영역에서 모든 입력을 받습니다. 창 클래스는 부모 창의 각 자식 창에 대해 동일할 필요가 없습니다. 즉, 애플리케이션이 다르게 보이고 다른 작업을 수행하는 자식 창으로 부모 창을 채울 수 있습니다. 예를 들어 대화 상자에는 다양한 유형의 컨트롤이 포함될 수 있으며, 각 컨트롤은 사용자의 다양한 형식의 데이터를 허용하는 자식 창입니다.

자식 창에는 부모 창이 하나만 있지만 부모 창에는 여러 자식 창이 있을 수 있습니다. 각 자식 창에는 자식 창이 있을 수 있습니다. 이 창 체인에서 각 자식 창을 원래 부모 창의 하위 창이라고 합니다. 애플리케이션은 IsChild 함수를 사용하여 지정된 창이 지정된 부모 창의 자식 창인지 하위 창인지 여부를 검색합니다.

EnumChildWindows 함수는 부모 창의 자식 창을 열거합니다. 그런 다음 EnumChildWindows 는 각 자식 창에 핸들을 애플리케이션 정의 콜백 함수로 전달합니다. 지정된 부모 창의 하위 창도 열거됩니다.

메시지

시스템은 자식 창의 입력 메시지를 자식 창에 직접 전달합니다. 메시지는 부모 창을 통해 전달되지 않습니다. 유일한 예외는 EnableWindow 함수에서 자식 창을 사용하지 않도록 설정한 경우입니다. 이 경우 시스템은 자식 창으로 이동했을 입력 메시지를 대신 부모 창으로 전달합니다. 이렇게 하면 부모 창에서 입력 메시지를 검사하고 필요한 경우 자식 창을 사용하도록 설정할 수 있습니다.

자식 창에는 고유한 정수 식별자가 있을 수 있습니다. 자식 창 식별자는 제어 창으로 작업할 때 중요합니다. 애플리케이션은 메시지를 전송하여 컨트롤의 작업을 지시합니다. 애플리케이션은 컨트롤의 자식 창 식별자를 사용하여 메시지를 컨트롤로 전달합니다. 또한 컨트롤은 부모 창에 알림 메시지를 보냅니다. 알림 메시지에는 부모가 메시지를 보낸 컨트롤을 식별하는 데 사용하는 컨트롤의 자식 창 식별자가 포함됩니다. 애플리케이션은 CreateWindowEx 함수의 hMenu 매개 변수를 메뉴 핸들이 아닌 값으로 설정하여 다른 유형의 자식 창에 대한 자식 창 식별자를 지정합니다.

계층화된 Windows

계층화된 창을 사용하면 모양이 복잡하거나 셰이프에 애니메이션 효과를 주거나 알파 혼합 효과를 사용하려는 창의 성능 및 시각 효과를 크게 향상시킬 수 있습니다. 시스템은 계층화된 창과 기본 애플리케이션의 창을 자동으로 구성하고 다시 칠합니다. 따라서 계층화된 창은 복잡한 창 영역의 일반적인 깜박임 없이 원활하게 렌더링됩니다. 또한 계층화된 창은 부분적으로 반투명할 수 있습니다( 즉, 알파 혼합).

계층화된 창을 만들려면 CreateWindowEx 함수를 호출할 때 WS_EX_LAYERED 확장 창 스타일을 지정하거나 SetWindowLong 함수를 호출하여 창을 만든 후 WS_EX_LAYERED 설정합니다. CreateWindowEx 호출 후에는 이 창에 대해 SetLayeredWindowAttributes 또는 UpdateLayeredWindow 함수가 호출될 때까지 계층화된 창이 표시되지 않습니다.

참고

Windows 8 시작하여 자식 창 및 최상위 창에서 WS_EX_LAYERED 사용할 수 있습니다. 이전 Windows 버전은 최상위 창에 대해서만 WS_EX_LAYERED 지원합니다.

 

지정된 계층화된 창의 불투명도 수준 또는 투명도 색 키를 설정하려면 SetLayeredWindowAttributes를 호출합니다. 호출 후에도 시스템은 창이 표시되거나 크기가 조정될 때 창을 페인트하도록 요청할 수 있습니다. 그러나 시스템이 계층화된 창의 이미지를 저장하기 때문에 시스템에서는 바탕 화면에서 상대적인 창 이동의 결과로 일부 부분이 표시되는 경우 창에 페인트를 요청하지 않습니다. 시스템에서 SetLayeredWindowAttributes 라는 창의 그리기를 화면 외부 메모리로 리디렉션하고 원하는 효과를 얻기 위해 다시 구성하기 때문에 레거시 애플리케이션은 창에 대해 반투명성 또는 투명도 효과를 추가하려는 경우 그리기 코드를 재구성할 필요가 없습니다.

더 빠르고 효율적인 애니메이션을 사용하거나 픽셀당 알파가 필요한 경우 UpdateLayeredWindow를 호출합니다. UpdateLayeredWindow 는 시스템이 SetLayeredWindowAttributes를 통해 제공하는 리디렉션 메커니즘을 사용하지 않고 애플리케이션이 계층화된 창의 모양과 콘텐츠를 직접 제공해야 하는 경우에 주로 사용해야 합니다. 또한 UpdateLayeredWindow 를 사용하면 시스템에서 리디렉션된 창의 이미지를 저장하는 데 필요한 추가 메모리가 필요하지 않으므로 메모리를 보다 효율적으로 사용합니다. 애니메이션 창의 효율성을 극대화하려면 UpdateLayeredWindow 를 호출하여 계층화된 창의 위치와 크기를 변경합니다. SetLayeredWindowAttributes가 호출된 후 계층화 스타일 비트가 지워지고 다시 설정될 때까지 후속 UpdateLayeredWindow 호출이 실패합니다.

계층화된 창의 적중 테스트는 창의 모양과 투명도를 기반으로 합니다. 즉, 색 키가 지정되거나 알파 값이 0인 창의 영역이 마우스 메시지를 통과할 수 있습니다. 그러나 계층화된 창에 WS_EX_TRANSPARENT 확장 창 스타일이 있는 경우 계층화된 창의 모양이 무시되고 마우스 이벤트가 계층화된 창 아래의 다른 창으로 전달됩니다.

windows Message-Only

메시지 전용 창을 사용하면 메시지를 보내고 받을 수 있습니다. 표시되지 않고, z 순서가 없고, 열거할 수 없으며, 브로드캐스트 메시지를 받지 않습니다. 창은 단순히 메시지를 디스패치합니다.

메시지 전용 창을 만들려면 CreateWindowEx 함수의 hWndParent 매개 변수에서 기존 메시지 전용 창에 대한 HWND_MESSAGE 상수 또는 핸들을 지정합니다. SetParent 함수의 hWndNewParent 매개 변수에 HWND_MESSAGE 지정하여 기존 창을 메시지 전용 창으로 변경할 수도 있습니다.

메시지 전용 창을 찾으려면 FindWindowEx 함수의 hwndParent 매개 변수에 HWND_MESSAGE 지정합니다. 또한 HwndParenthwndChildAfter 매개 변수가 모두 NULL인 경우 FindWindowEx는 메시지 전용 창과 최상위 창을 검색합니다.

창 관계

창이 사용자 또는 다른 창과 관련되는 여러 가지 방법이 있습니다. 창은 소유 창, 전경 창 또는 배경 창일 수 있습니다. 창에는 다른 창에 상대적인 z 순서도 있습니다. 자세한 내용은 아래 항목을 참조하세요.

전경 및 배경 창

각 프로세스에는 여러 스레드의 실행이 있을 수 있으며 각 스레드는 창을 만들 수 있습니다. 사용자가 현재 작업 중인 창을 만든 스레드를 포그라운드 스레드라고 하며 창을 포그라운드 창이라고 합니다. 다른 모든 스레드는 백그라운드 스레드이며 백그라운드 스레드에서 만든 창을 백그라운드 창이라고 합니다.

각 스레드에는 스레드가 수신하는 CPU 시간을 결정하는 우선 순위 수준이 있습니다. 애플리케이션은 스레드의 우선 순위 수준을 설정할 수 있지만 일반적으로 포그라운드 스레드는 백그라운드 스레드보다 약간 더 높은 우선 순위 수준을 줍니다. 우선 순위가 높기 때문에 포그라운드 스레드는 백그라운드 스레드보다 더 많은 CPU 시간을 받습니다. 포그라운드 스레드의 기본 우선 순위는 9입니다. 백그라운드 스레드의 기본 우선 순위는 7입니다.

사용자는 창을 클릭하거나 Alt+TAB 또는 ALT+ESC 키 조합을 사용하여 포그라운드 창을 설정합니다. 포그라운드 창에 대한 핸들을 검색하려면 GetForegroundWindow 함수를 사용합니다. 애플리케이션 창이 포그라운드 창인지 검사 GetForegroundWindow에서 반환된 핸들을 애플리케이션 창의 핸들과 비교합니다.

애플리케이션은 SetForegroundWindow 함수를 사용하여 포그라운드 창을 설정합니다.

시스템은 포그라운드 창을 설정할 수 있는 프로세스를 제한합니다. 프로세스는 다음과 같은 경우에만 포그라운드 창을 설정할 수 있습니다.

  • 다음 조건은 모두 true입니다.
    • SetForegroundWindow를 호출하는 프로세스는 UWP 앱이나 Windows 8 또는 8.1용으로 설계된 Windows 스토어 앱이 아닌 데스크톱 애플리케이션에 속합니다.
    • 전경 프로세스는 LockSetForegroundWindow 함수에 대한 이전 호출로 SetForegroundWindow에 대한 호출을 사용하지 않도록 설정하지 않았습니다.
    • 포그라운드 잠금 제한 시간이 만료되었습니다(SystemParametersInfoSPI_GETFOREGROUNDLOCKTIMEOUT 참조).
    • 활성 메뉴가 없습니다.
  • 또한 다음 조건 중 하나 이상이 true입니다.
    • 호출 프로세스는 포그라운드 프로세스입니다.
    • 호출 프로세스는 포그라운드 프로세스에 의해 시작되었습니다.
    • 현재 포그라운드 창이 없으므로 포그라운드 프로세스가 없습니다.
    • 호출 프로세스에서 마지막 입력 이벤트를 수신했습니다.
    • 포그라운드 프로세스 또는 호출 프로세스가 디버그되고 있습니다.

프로세스가 이러한 조건을 충족하더라도 전경 창을 설정할 수 있는 권한이 거부될 수 있습니다.

포그라운드 창을 설정할 수 있는 프로세스는 AllowSetForegroundWindow 함수를 호출하거나 BSF_ALLOWSFW 플래그를 사용하여 BroadcastSystemMessage 함수를 호출하여 다른 프로세스에서 포그라운드 창을 설정할 수 있습니다. 포그라운드 프로세스는 LockSetForegroundWindow 함수를 호출하여 SetForegroundWindow에 대한 호출을 사용하지 않도록 설정할 수 있습니다.

소유 Windows

겹치거나 팝업 창은 다른 겹치거나 팝업 창에서 소유할 수 있습니다. 소유되는 경우 창에 여러 제약 조건이 적용됩니다.

  • 소유된 창은 항상 z 순서의 소유자 위에 있습니다.
  • 소유자는 삭제될 때 시스템이 소유 창을 자동으로 삭제합니다.
  • 소유자가 최소화되면 소유 창이 숨겨집니다.

겹치거나 팝업 창만 소유자 창일 수 있습니다. 자식 창은 소유자 창일 수 없습니다. 애플리케이션은 WS_OVERLAPPED 또는 WS_POPUP 스타일로 창을 만들 때 소유자의 창 핸들을 CreateWindowExhwndParent 매개 변수로 지정하여 소유 창을 만듭니다. hwndParent 매개 변수는 겹치거나 팝업 창을 식별해야 합니다. hwndParent가 자식 창을 식별하는 경우 시스템은 자식 창의 최상위 부모 창에 소유권을 할당합니다. 소유 창을 만든 후 애플리케이션은 창의 소유권을 다른 창으로 이전할 수 없습니다.

대화 상자와 메시지 상자는 기본적으로 소유 창입니다. 애플리케이션은 대화 상자 또는 메시지 상자를 만드는 함수를 호출할 때 소유자 창을 지정합니다.

애플리케이션은 GW_OWNER 플래그와 함께 GetWindow 함수를 사용하여 창 소유자에 대한 핸들을 검색할 수 있습니다.

Z 순서

창의 z 순서 는 겹치는 창 스택에서 창의 위치를 나타냅니다. 이 창 스택은 가상 축인 z축을 따라 화면 바깥쪽으로 확장됩니다. z 순서 맨 위에 있는 창이 다른 모든 창과 겹칩니다. z 순서 아래쪽의 창은 다른 모든 창과 겹칩니다.

시스템은 단일 목록에서 z 순서를 유지 관리합니다. 최상위 창, 최상위 창 또는 자식 창인지 여부에 따라 z 순서에 창을 추가합니다. 맨 위 창은 활성 또는 전경 창인지 여부에 관계없이 맨 위가 아닌 다른 모든 창과 겹칩니다. 맨 위 창에는 WS_EX_TOPMOST 스타일이 있습니다. 맨 위에 있는 모든 창은 맨 위가 아닌 창 앞에 z 순서로 표시됩니다. 자식 창은 부모 창과 z 순서로 그룹화됩니다.

애플리케이션이 창을 만들 때 시스템은 동일한 형식의 창에 대해 창을 z 순서의 맨 위에 배치합니다. BringWindowToTop 함수를 사용하여 동일한 형식의 창에 대한 z 순서 맨 위에 창을 가져올 수 있습니다. SetWindowPosDeferWindowPos 함수를 사용하여 z 순서를 다시 정렬할 수 있습니다.

사용자는 다른 창을 활성화하여 z 순서를 변경합니다. 시스템은 동일한 형식의 창에 대해 활성 창을 z 순서의 맨 위에 배치합니다. 창이 z 순서의 맨 위에 오면 자식 창도 마찬가지입니다. GetTopWindow 함수를 사용하여 부모 창의 모든 자식 창을 검색하고 z 순서로 가장 높은 자식 창에 핸들을 반환할 수 있습니다. GetNextWindow 함수는 z 순서로 다음 또는 이전 창에 대한 핸들을 검색합니다.

창 상태 표시

지정된 시간에 창이 활성 또는 비활성일 수 있습니다. 숨김 또는 표시; 및 를 최소화, 최대화 또는 복원합니다. 이러한 품질은 창 표시 상태로 통칭됩니다. 다음 topics 창 표시 상태에 대해 설명합니다.

활성 창

활성 창은 사용자가 현재 작업 중인 애플리케이션의 최상위 창입니다. 사용자가 활성 창을 쉽게 식별할 수 있도록 시스템은 이를 z 순서의 맨 위에 배치하고 제목 표시줄 및 테두리의 색을 시스템 정의 활성 창 색으로 변경합니다. 최상위 창만 활성 창일 수 있습니다. 사용자가 자식 창으로 작업하는 경우 시스템은 자식 창과 연결된 최상위 부모 창을 활성화합니다.

시스템의 최상위 창은 한 번에 하나만 활성화됩니다. 사용자는 최상위 창(또는 자식 창 중 하나)을 클릭하거나 ALT+ESC 또는 Alt+TAB 키 조합을 사용하여 최상위 창을 활성화합니다. 애플리케이션은 SetActiveWindow 함수를 호출하여 최상위 창을 활성화합니다. 다른 함수로 인해 시스템에서 SetWindowPos, DeferWindowPos, SetWindowPlacementDestroyWindow를 비롯한 다른 최상위 창을 활성화할 수 있습니다. 애플리케이션은 언제든지 다른 최상위 창을 활성화할 수 있지만 사용자를 혼동하지 않도록 하려면 사용자 작업에 대한 응답으로만 활성화해야 합니다. 애플리케이션은 GetActiveWindow 함수를 사용하여 활성 창에 대한 핸들을 검색합니다.

활성화가 한 애플리케이션의 최상위 창에서 다른 애플리케이션의 최상위 창으로 변경되면 시스템은 두 애플리케이션에 WM_ACTIVATEAPP 메시지를 보내 변경 내용을 알립니다. 활성화가 동일한 애플리케이션의 다른 최상위 창으로 변경되면 시스템은 두 창에 WM_ACTIVATE 메시지를 보냅니다.

사용 안 함 Windows

창을 사용하지 않도록 설정할 수 있습니다. 비활성화된 창은 사용자로부터 키보드 또는 마우스 입력을 받지 않지만 다른 창, 다른 응용 프로그램 및 시스템에서 메시지를 받을 수 있습니다. 애플리케이션은 일반적으로 사용자가 창을 사용하지 못하도록 창을 사용하지 않도록 설정합니다. 예를 들어 애플리케이션은 사용자가 선택하지 못하도록 대화 상자에서 푸시 단추를 사용하지 않도록 설정할 수 있습니다. 애플리케이션은 언제든지 비활성화된 창을 사용하도록 설정할 수 있습니다. 창을 사용하도록 설정하면 일반 입력이 복원됩니다.

기본적으로 창은 만들 때 사용하도록 설정됩니다. 그러나 애플리케이션은 WS_DISABLED 스타일을 지정하여 새 창을 사용하지 않도록 설정할 수 있습니다. 애플리케이션은 EnableWindow 함수를 사용하여 기존 창을 사용하거나 사용하지 않도록 설정합니다. 사용 상태가 변경될 때 시스템은 WM_ENABLE 메시지를 창으로 보냅니다. 애플리케이션은 IsWindowEnabled 함수를 사용하여 창을 사용할 수 있는지 여부를 확인할 수 있습니다.

자식 창을 사용하지 않도록 설정하면 시스템에서 자식의 마우스 입력 메시지를 부모 창에 전달합니다. 부모는 메시지를 사용하여 자식 창을 사용하도록 설정할지 여부를 결정합니다. 자세한 내용은 마우스 입력을 참조하세요.

한 번에 하나의 창만 키보드 입력을 받을 수 있습니다. 이 창에는 키보드 포커스가 있다고 합니다. 애플리케이션이 EnableWindow 함수를 사용하여 키보드 포커스 창을 사용하지 않도록 설정하는 경우 창은 사용하지 않도록 설정될 뿐 아니라 키보드 포커스를 잃게 됩니다. 그런 다음 EnableWindow 는 키보드 포커스를 NULL로 설정합니다. 즉, 창에 포커스가 없습니다. 자식 창 또는 다른 하위 창에 키보드 포커스가 있는 경우 부모 창을 사용하지 않도록 설정하면 하위 창에서 포커스가 손실됩니다. 자세한 내용은 키보드 입력을 참조하세요.

창 표시 유형

창은 표시하거나 숨길 수 있습니다. 화면에 표시되는 창 이 표시됩니다. 숨겨진 창을 그리지 않음으로써 숨깁니다. 창이 표시되면 사용자는 창에 입력을 하고 창의 출력을 볼 수 있습니다. 창이 숨겨지면 효과적으로 사용할 수 없습니다. 숨겨진 창은 시스템 또는 다른 창에서 발생한 메시지를 처리할 수 있지만, 사용자가 입력한 내용을 처리하거나 출력 내용을 표시할 수 없습니다. 애플리케이션은 창을 만들 때 창의 표시 상태를 설정합니다. 나중에 애플리케이션은 표시 유형 상태를 변경할 수 있습니다.

창에 대해 WS_VISIBLE 스타일을 설정하면 창이 표시됩니다. 기본적으로 CreateWindowEx 함수는 애플리케이션이 WS_VISIBLE 스타일을 지정하지 않는 한 숨겨진 창을 만듭니다. 일반적으로 애플리케이션은 생성 프로세스의 세부 정보를 사용자에게 숨기도록 창을 만든 후 WS_VISIBLE 스타일을 설정합니다. 예를 들어 애플리케이션은 창의 모양을 사용자 지정하는 동안 새 창을 숨김 상태로 유지할 수 있습니다. WS_VISIBLE 스타일이 CreateWindowEx에 지정된 경우 시스템은 창을 만든 후 표시하기 전에 창에 WM_SHOWWINDOW 메시지를 보냅니다.

애플리케이션은 IsWindowVisible 함수를 사용하여 창이 표시되는지 여부를 확인할 수 있습니다. 애플리케이션은 ShowWindow, SetWindowPos, DeferWindowPos 또는 SetWindowPlacement 또는 SetWindowLong 함수를 사용하여 창을 표시하거나 숨길 수 있습니다. 이러한 함수는 창의 WS_VISIBLE 스타일을 설정하거나 제거하여 창을 표시하거나 숨깁니다. 또한 WM_SHOWWINDOW 메시지를 표시하거나 숨기기 전에 창으로 보냅니다.

소유자 창이 최소화되면 시스템은 연결된 소유 창을 자동으로 숨깁니다. 마찬가지로 소유자 창이 복원되면 시스템은 연결된 소유 창을 자동으로 표시합니다. 두 경우 모두 시스템은 WM_SHOWWINDOW 메시지를 숨기거나 표시하기 전에 소유 창으로 보냅니다. 경우에 따라 애플리케이션은 소유자를 최소화하거나 숨기지 않고도 소유 창을 숨겨야 할 수 있습니다. 이 경우 애플리케이션은 ShowOwnedPopups 함수를 사용합니다. 이 함수는 소유된 모든 창의 WS_VISIBLE 스타일을 설정하거나 제거하고 WM_SHOWWINDOW 메시지를 숨기거나 표시하기 전에 소유 창으로 보냅니다. 소유자 창을 숨기면 소유 창의 표시 유형 상태에 영향을 주지 않습니다.

부모 창이 표시되면 연결된 자식 창도 표시됩니다. 마찬가지로 부모 창이 숨겨지면 자식 창도 숨겨집니다. 부모 창을 최소화해도 자식 창의 표시 유형 상태에는 영향을 주지 않습니다. 즉, 자식 창은 부모와 함께 최소화되지만 WS_VISIBLE 스타일은 변경되지 않습니다.

창에 WS_VISIBLE 스타일이 있더라도 사용자가 화면에서 창을 볼 수 없을 수 있습니다. 다른 창이 완전히 겹치거나 화면 가장자리를 넘어 이동되었을 수 있습니다. 또한 표시되는 자식 창에는 부모-자식 관계에 의해 설정된 클리핑 규칙이 적용됩니다. 창의 부모 창이 표시되지 않으면 창도 표시되지 않습니다. 부모 창이 화면 가장자리 이상으로 이동하면 자식 창이 부모의 왼쪽 위 모서리를 기준으로 그려지므로 자식 창도 이동합니다. 예를 들어 자식 창과 부모 창 모두 WS_VISIBLE 스타일을 사용하더라도 사용자가 자식 창을 볼 수 없을 정도로 화면 가장자리에서 자식 창이 포함된 부모 창을 이동할 수 있습니다.

최소화, 최대화 및 복원된 Windows

최대화된 창WS_MAXIMIZE 스타일을 가진 창입니다. 기본적으로 시스템은 화면을 채우거나 자식 창인 경우에는 부모 창의 클라이언트 영역을 채우도록 최대화된 창을 확대합니다. 창의 크기를 최대화된 창의 동일한 크기로 설정할 수 있지만 최대화된 창은 약간 다릅니다. 시스템은 자동으로 창의 제목 표시줄을 화면 위쪽 또는 부모 창의 클라이언트 영역 위쪽으로 이동합니다. 또한 시스템은 창의 크기 조정 테두리와 제목 표시줄의 창 위치 지정 기능을 사용하지 않도록 설정합니다(사용자가 제목 표시줄을 끌어 창을 이동할 수 없도록).

최소화된 창WS_MINIMIZE 스타일을 가진 창입니다. 기본적으로 시스템은 최소화된 창을 작업 표시줄 단추 크기로 줄인 다음 작업 표시줄로 이동합니다. 복원된 창은 이전 크기 및 위치, 즉 최소화되거나 최대화되기 전의 크기로 반환된 창입니다.

애플리케이션이 CreateWindowEx 함수에서 WS_MAXIMIZE 또는 WS_MINIMIZE 스타일을 지정하면 창이 처음에 최대화되거나 최소화됩니다. 창을 만든 후 애플리케이션은 CloseWindow 함수를 사용하여 창을 최소화할 수 있습니다. ArrangeIconicWindows 함수는 바탕 화면의 아이콘을 정렬하거나 부모 창에서 부모 창의 최소화된 자식 창을 정렬합니다. OpenIcon 함수는 최소화된 창을 이전 크기와 위치로 복원합니다.

ShowWindow 함수는 창을 최소화, 최대화 또는 복원할 수 있습니다. 창의 표시 유형 및 활성화 상태를 설정할 수도 있습니다. SetWindowPlacement 함수는 ShowWindow와 동일한 기능을 포함하지만 창의 기본 최소화, 최대화 및 복원된 위치를 재정의할 수 있습니다.

IsZoomedIsIconic 함수는 지정된 창이 각각 최대화 또는 최소화되는지 여부를 결정합니다. GetWindowPlacement 함수는 창의 최소화, 최대화 및 복원된 위치를 검색하고 창의 표시 상태도 결정합니다.

시스템은 최소화된 창을 최대화하거나 복원하는 명령을 받으면 창에 WM_QUERYOPEN 메시지를 보냅니다. 창 프로시저가 FALSE를 반환하면 시스템은 최대화 또는 복원 명령을 무시합니다.

시스템은 최대화된 창의 크기와 위치를 자동으로 최대화된 창의 시스템 정의 기본값으로 설정합니다. 이러한 기본값을 재정의하기 위해 애플리케이션은 SetWindowPlacement 함수를 호출하거나 시스템이 창을 최대화하려고 할 때 창에서 수신하는 WM_GETMINMAXINFO 메시지를 처리할 수 있습니다. WM_GETMINMAXINFO 시스템에서 최대 크기 및 위치를 설정하는 데 사용하는 값을 포함하는 MINMAXINFO 구조체에 대한 포인터를 포함합니다. 이러한 값을 바꾸면 기본값이 재정의됩니다.

창 크기 및 위치

창의 크기와 위치는 화면 또는 부모 창을 기준으로 좌표로 지정된 경계 사각형으로 표현됩니다. 최상위 창의 좌표는 화면의 왼쪽 위 모서리를 기준으로 합니다. 자식 창의 좌표는 부모 창의 왼쪽 위 모서리를 기준으로 합니다. 애플리케이션은 창을 만들 때 창의 초기 크기와 위치를 지정하지만 언제든지 창의 크기와 위치를 변경할 수 있습니다. 자세한 내용은 채워진 도형을 참조하세요.

이 섹션에서는 다음 항목을 다룹니다.

기본 크기 및 위치

애플리케이션을 사용하면 시스템이 CreateWindowEx에서 CW_USEDEFAULT 지정하여 최상위 창의 초기 크기 또는 위치를 계산할 수 있습니다. 애플리케이션이 창의 좌표를 CW_USEDEFAULT 설정하고 다른 최상위 창을 만들지 않은 경우 시스템은 화면의 왼쪽 위 모서리를 기준으로 새 창의 위치를 설정합니다. 그렇지 않으면 애플리케이션이 가장 최근에 만든 최상위 창의 위치를 기준으로 위치를 설정합니다. 너비 및 높이 매개 변수가 CW_USEDEFAULT 설정되면 시스템은 새 창의 크기를 계산합니다. 애플리케이션이 다른 최상위 창을 만든 경우 시스템은 애플리케이션에서 가장 최근에 만든 최상위 창의 크기에 따라 새 창의 크기를 기반으로 합니다. 자식 또는 팝업 창을 만들 때 CW_USEDEFAULT 지정하면 시스템에서 창의 크기를 기본 최소 창 크기로 설정합니다.

추적 크기

시스템은 WS_THICKFRAME 스타일의 창에 대해 최소 및 최대 추적 크기를 유지합니다. 이 스타일이 있는 창에는 크기 조정 테두리가 있습니다. 최소 추적 크기는 창의 크기 조정 테두리를 끌어 생성할 수 있는 가장 작은 창 크기입니다. 마찬가지로 최대 추적 크기 는 크기 조정 테두리를 끌어 생성할 수 있는 가장 큰 창 크기입니다.

시스템에서 창을 만들 때 창의 최소 및 최대 추적 크기는 시스템 정의 기본값으로 설정됩니다. 애플리케이션은 기본값을 검색하고 WM_GETMINMAXINFO 메시지를 처리하여 재정의할 수 있습니다. 자세한 내용은 메시지 크기 및 위치를 참조하세요.

시스템 명령

창 메뉴가 있는 애플리케이션은 시스템 명령을 전송하여 해당 창의 크기와 위치를 변경할 수 있습니다. 사용자가 창 메뉴에서 명령을 선택하면 시스템 명령이 생성됩니다. 애플리케이션은 창에 WM_SYSCOMMAND 메시지를 보내 사용자 작업을 에뮬레이트할 수 있습니다. 다음 시스템 명령은 창의 크기와 위치에 영향을 줍니다.

명령 설명
SC_CLOSE 창을 닫습니다. 이 명령은 창에 WM_CLOSE 메시지를 보냅니다. 창은 클린 자신을 파괴하는 데 필요한 모든 단계를 수행합니다.
SC_MAXIMIZE 창을 최대화합니다.
SC_MINIMIZE 창을 최소화합니다.
SC_MOVE 창을 이동합니다.
SC_RESTORE 최소화되거나 최대화된 창을 이전 크기와 위치로 복원합니다.
SC_SIZE 크기 명령을 시작합니다. 창의 크기를 변경하려면 마우스 또는 키보드를 사용합니다.

 

크기 및 위치 함수

창을 만든 후 애플리케이션은 SetWindowPlacement, MoveWindow, SetWindowPosDeferWindowPos를 비롯한 여러 함수 중 하나를 호출하여 창의 크기 또는 위치를 설정할 수 있습니다. SetWindowPlacement 는 창의 최소화된 위치, 최대화된 위치, 복원된 크기 및 위치 및 표시 상태를 설정합니다. MoveWindowSetWindowPos 함수는 비슷합니다. 둘 다 단일 애플리케이션 창의 크기 또는 위치를 설정합니다. SetWindowPos 함수에는 창의 표시 상태에 영향을 주는 플래그 집합이 포함됩니다. MoveWindow에는 이러한 플래그가 포함되지 않습니다. BeginDeferWindowPos, DeferWindowPosEndDeferWindowPos 함수를 사용하여 크기, 위치, z 순서의 위치, 상태 표시 등 여러 창의 위치를 동시에 설정합니다.

애플리케이션은 GetWindowRect 함수를 사용하여 창 경계 사각형의 좌표를 검색할 수 있습니다. GetWindowRectRECT 구조체를 창의 왼쪽 위와 오른쪽 아래 모서리의 좌표로 채웁니다. 좌표는 자식 창의 경우에도 화면의 왼쪽 위 모서리를 기준으로 합니다. ScreenToClient 또는 MapWindowPoints 함수는 자식 창의 경계 사각형의 화면 좌표를 부모 창의 클라이언트 영역을 기준으로 좌표에 매핑합니다.

GetClientRect 함수는 창의 클라이언트 영역의 좌표를 검색합니다. GetClientRectRECT 구조체를 클라이언트 영역의 왼쪽 위와 오른쪽 아래 모서리의 좌표로 채우지만 좌표는 클라이언트 영역 자체에 상대적입니다. 즉, 클라이언트 영역의 왼쪽 위 모서리의 좌표는 항상(0,0)이고 오른쪽 아래 모서리의 좌표는 클라이언트 영역의 너비와 높이입니다.

CascadeWindows 함수는 바탕 화면의 창을 계단식으로 배열하거나 지정된 부모 창의 자식 창을 계단식으로 연결합니다. TileWindows 함수는 바탕 화면의 창을 타일로 표시하거나 지정된 부모 창의 자식 창을 타일로 표시합니다.

메시지 크기 및 위치

시스템은 크기 또는 위치가 변경되는 창에 WM_GETMINMAXINFO 메시지를 보냅니다. 예를 들어 사용자가 창 메뉴에서 이동 또는 크기를 클릭하거나 크기 조정 테두리 또는 제목 표시줄을 클릭하면 메시지가 전송됩니다. 애플리케이션이 SetWindowPos 를 호출하여 창을 이동하거나 크기를 조정할 때도 메시지가 전송됩니다. WM_GETMINMAXINFO 창의 기본 최대 크기 및 위치와 기본 최소 및 최대 추적 크기를 포함하는 MINMAXINFO 구조체에 대한 포인터를 포함합니다. 애플리케이션은 WM_GETMINMAXINFO 처리하고 MINMAXINFO의 적절한 멤버를 설정하여 기본값을 재정의할 수 있습니다. WM_GETMINMAXINFO 받으려면 창에 WS_THICKFRAME 또는 WS_CAPTION 스타일이 있어야 합니다. WS_THICKFRAME 스타일이 있는 창은 창 만들기 프로세스와 이동 또는 크기 조정 중에 이 메시지를 받습니다.

시스템은 크기, 위치, z 순서의 위치 또는 표시 상태가 변경되는 창에 WM_WINDOWPOSCHANGING 메시지를 보냅니다. 이 메시지에는 창의 새 크기, 위치, z 순서의 위치 및 표시 상태를 지정하는 WINDOWPOS 구조체에 대한 포인터가 포함되어 있습니다. WINDOWPOS의 멤버를 설정하면 애플리케이션이 창의 새 크기, 위치 및 모양에 영향을 줄 수 있습니다.

창의 크기, 위치, z 순서의 위치 또는 표시 상태를 변경한 후 시스템은 WM_WINDOWPOSCHANGED 메시지를 창으로 보냅니다. 이 메시지에는 창에 새 크기, 위치, z 순서의 위치 및 표시 상태를 알리는 WINDOWPOS 에 대한 포인터가 포함되어 있습니다. WM_WINDOWPOSCHANGED 함께 전달되는 WINDOWPOS 구조체의 멤버를 설정해도 창에는 영향을 주지 않습니다. WM_SIZE 처리하고 메시지를 WM_MOVE 창은 WM_WINDOWPOSCHANGED DefWindowProc 함수에 전달해야 합니다. 그렇지 않으면 시스템에서 창에 WM_SIZEWM_MOVE 메시지를 보내지 않습니다.

시스템은 창이 만들어지거나 크기가 조정될 때 창에 WM_NCCALCSIZE 메시지를 보냅니다. 시스템은 메시지를 사용하여 창의 클라이언트 영역 크기와 창의 왼쪽 위 모서리를 기준으로 하는 클라이언트 영역의 위치를 계산합니다. 창은 일반적으로 이 메시지를 기본 창 프로시저에 전달합니다. 그러나 이 메시지는 창의 비클라이언트 영역을 사용자 지정하거나 창 크기가 조정될 때 클라이언트 영역의 일부를 유지하는 애플리케이션에서 유용할 수 있습니다. 자세한 내용은 그리기 및 그리기를 참조하세요.

창 애니메이션

AnimateWindow 함수를 사용하여 창을 표시하거나 숨길 때 특수 효과를 생성할 수 있습니다. 이러한 방식으로 창에 애니메이션이 적용되면 시스템은 AnimateWindow 호출에서 지정한 플래그에 따라 창을 롤, 슬라이드 또는 페이드합니다.

기본적으로 시스템은 롤 애니메이션을 사용합니다. 이 효과를 사용하면 창이 열리거나(창을 표시) 닫힌 롤(창 숨기기)으로 표시됩니다. dwFlags 매개 변수를 사용하여 창이 가로, 세로 또는 대각선으로 롤되는지 여부를 지정할 수 있습니다.

AW_SLIDE 플래그를 지정하면 시스템에서 슬라이드 애니메이션을 사용합니다. 이 효과를 사용하면 창이 보기로 밀거나(창을 표시) 보이지 않는 것처럼 보입니다(창 숨기기). dwFlags 매개 변수를 사용하여 창이 가로, 세로 또는 대각선으로 슬라이드되는지 여부를 지정할 수 있습니다.

AW_BLEND 플래그를 지정하면 시스템에서 알파 혼합 페이드를 사용합니다.

AW_CENTER 플래그를 사용하여 창이 안쪽으로 축소되거나 바깥쪽으로 확장되도록 할 수도 있습니다.

창 레이아웃 및 미러링

창 레이아웃은 텍스트 및 Windows GDI(그래픽 디바이스 인터페이스) 개체가 창 또는 DC(디바이스 컨텍스트)에 배치되는 방법을 정의합니다. 영어, 프랑스어 및 독일어와 같은 일부 언어에는 LTR(왼쪽에서 오른쪽) 레이아웃이 필요합니다. 아랍어 및 히브리어와 같은 다른 언어에는 RTL(오른쪽에서 왼쪽) 레이아웃이 필요합니다. 창 레이아웃은 텍스트에 적용되지만 비트맵, 아이콘, 원점 위치, 단추, 계단식 트리 컨트롤, 왼쪽 또는 오른쪽으로 이동하면 가로 좌표가 증가하는지 여부 등 창의 다른 GDI 요소에도 영향을 줍니다. 예를 들어 애플리케이션이 RTL 레이아웃을 설정한 후 원본은 창 또는 디바이스의 오른쪽 가장자리에 배치되고 왼쪽으로 이동하면 가로 좌표를 나타내는 숫자가 증가합니다. 그러나 모든 개체가 창 레이아웃의 영향을 받는 것은 아닙니다. 예를 들어 메타파일 및 프린터 DC와 같이 창과 연결되지 않은 대화 상자, 메시지 상자 및 디바이스 컨텍스트의 레이아웃은 별도로 처리해야 합니다. 이에 대한 자세한 내용은 이 항목의 뒷부분에서 설명합니다.

창 함수를 사용하면 아랍어 및 히브리어 버전의 Windows에서 창 레이아웃을 지정하거나 변경할 수 있습니다. 스타일이 CS_OWNDC 창이나 GM_ADVANCED 그래픽 모드가 있는 DC에서는 RTL 레이아웃(미러링이라고도 함)으로 변경이 지원되지 않습니다.

기본적으로 창 레이아웃은 LTR(왼쪽에서 오른쪽)입니다. RTL 창 레이아웃을 설정하려면 스타일 WS_EX_LAYOUTRTL사용하여 CreateWindowEx를 호출합니다. 또한 기본적으로 자식 창(즉, createWindow 또는 CreateWindowEx 호출에서 WS_CHILD 스타일과 유효한 부모 hWnd 매개 변수로 만든 창)은 부모와 동일한 레이아웃을 줍니다. 모든 자식 창에 대한 미러링 상속을 사용하지 않도록 설정하려면 CreateWindowEx 호출에서 WS_EX_NOINHERITLAYOUT 지정합니다. 미러링이 소유 창(WS_CHILD 스타일 없이 만든 창) 또는 CreateWindowEx에서 부모 hWnd 매개 변수를 사용하여 만든 창이 NULL로 설정된 경우 상속되지 않습니다. 개별 창에 대한 미러링 상속을 사용하지 않도록 설정하려면 GetWindowLongSetWindowLong을 사용하여 WM_NCCREATE 메시지를 처리하여 WS_EX_LAYOUTRTL 플래그를 끕니다. 이 처리는 필요한 다른 모든 처리에 추가됩니다. 다음 코드 조각은 이 작업을 수행하는 방법을 보여줍니다.

SetWindowLong (hWnd, 
               GWL_EXSTYLE, 
               GetWindowLong(hWnd,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL))

SetProcessDefaultLayout(LAYOUT_RTL)을 호출하여 기본 레이아웃을 RTL로 설정할 수 있습니다. 호출 후에 만든 모든 창은 미러되지만 기존 창은 영향을 받지 않습니다. 기본 미러링을 해제하려면 SetProcessDefaultLayout(0)을 호출합니다.

SetProcessDefaultLayout은 미러된 창의 DC만 미러링합니다. DC를 미러 위해 SetLayout(hdc, LAYOUT_RTL)을 호출합니다. 자세한 내용은 이 항목의 뒷부분에 나오는 Windows와 연결되지 않은 미러링 디바이스 컨텍스트에 대한 토론을 참조하세요.

미러된 창의 비트맵 및 아이콘도 기본적으로 미러링됩니다. 그러나 이러한 모든 것을 미러링해야 하는 것은 아닙니다. 예를 들어 텍스트, 비즈니스 로고 또는 아날로그 시계가 있는 시계는 미러링하면 안 됩니다. 비트맵의 미러링을 사용하지 않도록 설정하려면 dwLayout에 설정된 LAYOUT_BITMAPORIENTATIONPRESERVED 비트로 SetLayout을 호출합니다. DC에서 미러링을 사용하지 않도록 설정하려면 SetLayout(hdc, 0)을 호출합니다.

현재 기본 레이아웃을 쿼리하려면 GetProcessDefaultLayout을 호출합니다. 성공적으로 반환되면 pdwDefaultLayout 에는 LAYOUT_RTL 또는 0이 포함됩니다. 디바이스 컨텍스트의 레이아웃 설정을 쿼리하려면 GetLayout을 호출합니다. 성공적으로 반환되면 GetLayout 은 LAYOUT_RTL 및 LAYOUT_BITMAPORIENTATIONPRESERVED 비트의 설정에 따라 레이아웃 설정을 나타내는 DWORD 를 반환합니다.

창을 만든 후 SetWindowLong 함수를 사용하여 레이아웃을 변경합니다. 예를 들어 사용자가 기존 창의 사용자 인터페이스 언어를 아랍어 또는 히브리어에서 독일어로 변경하는 경우에 필요합니다. 그러나 기존 창의 레이아웃을 변경하는 경우 창을 무효화하고 업데이트하여 창 내용이 모두 동일한 레이아웃에 그려지도록 해야 합니다. 다음 코드 예제는 필요에 따라 창 레이아웃을 변경하는 샘플 코드의 예제입니다.

// Using ANSI versions of GetWindowLong and SetWindowLong because Unicode
// is not needed for these calls

lExStyles = GetWindowLongA(hWnd, GWL_EXSTYLE);

// Check whether new layout is opposite the current layout
if (!!(pLState -> IsRTLLayout) != !!(lExStyles & WS_EX_LAYOUTRTL))
{
    // the following lines will update the window layout

    lExStyles ^= WS_EX_LAYOUTRTL;        // toggle layout
    SetWindowLongA(hWnd, GWL_EXSTYLE, lExStyles);
    InvalidateRect(hWnd, NULL, TRUE);    // to update layout in the client area
}

미러링에서는 "left" 및 "right" 대신 "near" 및 "far"를 고려해야 합니다. 이렇게 하지 않으면 문제가 발생할 수 있습니다. 미러된 창에서 문제를 일으키는 일반적인 코딩 사례 중 하나는 화면 좌표와 클라이언트 좌표 간에 매핑할 때 발생합니다. 예를 들어 애플리케이션은 다음과 유사한 코드를 사용하여 창에 컨트롤을 배치하는 경우가 많습니다.

// DO NOT USE THIS IF APPLICATION MIRRORS THE WINDOW

// get coordinates of the window in screen coordinates
GetWindowRect(hControl, (LPRECT) &rControlRect);  

// map screen coordinates to client coordinates in dialog
ScreenToClient(hDialog, (LPPOINT) &rControlRect.left); 
ScreenToClient(hDialog, (LPPOINT) &rControlRect.right);

이렇게 하면 사각형의 왼쪽 가장자리가 미러링된 창의 오른쪽 가장자리가 되고 그 반대의 경우도 마찬가지이므로 미러링에 문제가 발생합니다. 이 문제를 방지하려면 다음과 같이 ScreenToClient 호출을 MapWindowPoints 호출로 바꿉니다.

// USE THIS FOR MIRRORING

GetWindowRect(hControl, (LPRECT) &rControlRect);
MapWindowPoints(NULL, hDialog, (LPPOINT) &rControlRect, 2)

이 코드는 미러링을 지원하는 플랫폼에서 클라이언트 창이 미러링될 때 왼쪽 및 오른쪽 점 좌표를 교환하도록 MapWindowPoints 가 수정되기 때문에 작동합니다. 자세한 내용은 MapWindowPoints의 설명 섹션을 참조하세요.

미러된 창에서 문제를 일으킬 수 있는 또 다른 일반적인 방법은 클라이언트 좌표 대신 화면 좌표의 오프셋을 사용하여 클라이언트 창에 개체를 배치하는 것입니다. 예를 들어 다음 코드에서는 화면 좌표의 차이를 클라이언트 좌표의 x 위치로 사용하여 대화 상자에 컨트롤을 배치합니다.

// OK if LTR layout and mapping mode of client is MM_TEXT,
// but WRONG for a mirrored dialog 

RECT rdDialog;
RECT rcControl;

HWND hControl = GetDlgItem(hDlg, IDD_CONTROL);
GetWindowRect(hDlg, &rcDialog);             // gets rect in screen coordinates
GetWindowRect(hControl, &rcControl);
MoveWindow(hControl,
           rcControl.left - rcDialog.left,  // uses x position in client coords
           rcControl.top - rcDialog.top,
           nWidth,
           nHeight,
           FALSE);

클라이언트 좌표의 새 x 위치는 컨트롤의 왼쪽 가장자리와 화면 좌표의 대화 상자의 차이에 해당하기 때문에 대화 상자 창에 LTR(왼쪽에서 오른쪽) 레이아웃이 있고 클라이언트의 매핑 모드가 MM_TEXT 경우 이 코드는 괜찮습니다. 그러나 미러된 대화 상자에서 왼쪽과 오른쪽은 역방향이므로 다음과 같이 MapWindowPoints를 사용해야 합니다.

RECT rcDialog;
RECT rcControl;

HWND hControl - GetDlgItem(hDlg, IDD_CONTROL);
GetWindowRect(hControl, &rcControl);

// MapWindowPoints works correctly in both mirrored and non-mirrored windows.
MapWindowPoints(NULL, hDlg, (LPPOINT) &rcControl, 2);

// Now rcControl is in client coordinates.
MoveWindow(hControl, rcControl.left, rcControl.top, nWidth, nHeight, FALSE)

미러링 대화 상자 및 메시지 상자

대화 상자와 메시지 상자는 레이아웃을 상속하지 않으므로 레이아웃을 명시적으로 설정해야 합니다. 메시지 상자를 미러 MB_RTLREADING 옵션을 사용하여MessageBox 또는 MessageBoxEx를 호출합니다. 대화 상자를 오른쪽에서 왼쪽으로 레이아웃하려면 대화 상자 템플릿 구조 DLGTEMPLATEEX의 확장 스타일 WS_EX_LAYOUTRTL 사용합니다. 속성 시트는 대화 상자의 특수한 사례입니다. 각 탭은 별도의 대화 상자로 처리되므로 미러링하려는 모든 탭에 WS_EX_LAYOUTRTL 스타일을 포함해야 합니다.

미러링 디바이스 컨텍스트가 창과 연결되지 않음

메타파일 또는 프린터 DC와 같이 창과 연결되지 않은 DC는 레이아웃을 상속하지 않으므로 레이아웃을 명시적으로 설정해야 합니다. 디바이스 컨텍스트 레이아웃을 변경하려면 SetLayout 함수를 사용합니다.

SetLayout 함수는 창에서 거의 사용되지 않습니다. 일반적으로 windows는 WM_PAINT 메시지를 처리하는 경우에만 연결된 DC를 받습니다. 경우에 따라 프로그램에서 GetDC를 호출하여 창에 대한 DC를 만듭니다. 어느 쪽이든 DC의 초기 레이아웃은 창의 WS_EX_LAYOUTRTL 플래그에 따라 BeginPaint 또는 GetDC 에 의해 설정됩니다.

GetWindowOrgEx, GetWindowExtEx, GetViewportOrgExGetViewportExtEx에서 반환되는 값은 SetLayout 호출의 영향을 받지 않습니다.

레이아웃이 RTL이면 GetMapMode 는 MM_TEXT 대신 MM_ANISOTROPIC 반환합니다. MM_TEXT SetMapMode를 호출하면 올바르게 작동합니다. GetMapMode의 반환 값만 영향을 받습니다. 마찬가지로 매핑 모드가 MM_TEXT 때 SetLayout(hdc, LAYOUT_RTL)을 호출하면 보고된 매핑 모드가 MM_ANISOTROPIC 변경됩니다.

창 파괴

일반적으로 애플리케이션은 만든 모든 창을 삭제해야 합니다. 이 작업은 DestroyWindow 함수를 사용하여 수행합니다. 창이 제거되면 시스템이 창이 표시되면 창을 숨기고 창과 연결된 내부 데이터를 제거합니다. 그러면 더 이상 애플리케이션에서 사용할 수 없는 창 핸들이 무효화됩니다.

애플리케이션은 만든 후 생성되는 많은 창을 삭제합니다. 예를 들어 애플리케이션은 일반적으로 사용자가 작업을 계속할 수 있는 충분한 입력이 있는 즉시 대화 상자 창을 삭제합니다. 결국 애플리케이션은 종료하기 전에 애플리케이션의 기본 창을 삭제합니다.

창을 삭제하기 전에 애플리케이션은 창과 연결된 데이터를 저장하거나 제거해야 하며, 창에 할당된 시스템 리소스를 해제해야 합니다. 애플리케이션이 리소스를 해제하지 않으면 시스템에서 애플리케이션에서 해제하지 않은 리소스를 해제합니다.

창을 삭제해도 창이 만들어지는 창 클래스에는 영향을 주지 않습니다. 해당 클래스를 사용하여 새 창을 만들 수 있으며 해당 클래스의 기존 창은 계속 작동합니다. 창을 삭제하면 창의 하위 창도 삭제됩니다. DestroyWindow 함수는 먼저 WM_DESTROY 메시지를 창으로 보낸 다음 자식 창과 하위 창으로 보냅니다. 이러한 방식으로 파괴되는 창의 모든 하위 창도 파괴됩니다.

창 메뉴가 있는 창은 사용자가 닫기를 클릭하면 WM_CLOSE 메시지를 받습니다. 이 메시지를 처리하면 애플리케이션에서 창을 삭제하기 전에 사용자에게 확인 메시지를 표시할 수 있습니다. 사용자가 창을 제거해야 한다고 확인하면 애플리케이션에서 DestroyWindow 함수를 호출하여 창을 삭제할 수 있습니다.

제거되는 창이 활성 창이면 활성 및 포커스 상태가 모두 다른 창으로 전송됩니다. 활성 창이 되는 창은 ALT+ESC 키 조합에 따라 결정되는 다음 창입니다. 그러면 새 활성 창에서 키보드 포커스를 받는 창을 결정합니다.