정리

[Win32 API] Window Styles

저장소/VC++
글 싸기가 귀찮아서 걍 검색한 내용.
원문 작성자님 감사합니다. ㅎㅎ;;

출처 : http://blog.naver.com/kimgudtjr/140095980103


[윈도우 스타일]

 

CreateWindow 함수의 세번째 인자로 윈도우의 스타일을 지정할 수 있는데..

WinUser.h  라는 헤더파일을 보면 여러가지 종류가 정의도어 있다.

독자가 그 파일을 열어 봤더니 아래와 같은 종류들이 나열 되어 있었다.

 

------------------ WinUser.h 에서 윈도우 스타일 정의------------------------

/*
 * Window Styles
 */
#define WS_OVERLAPPED       0x00000000L //디폴트 윈도우
#define WS_POPUP            0x80000000L  // 팝업 윈도우를 만든다. WS_CHILD와 함께 쓸수 없다.
#define WS_CHILD            0x40000000L  //차일드 윈도우를 만든다. WS_POPUP와 함께 쓸 수 없다.
#define WS_MINIMIZE         0x20000000L  //최초 최소화된 상태로 윈도우를 만든다.
#define WS_VISIBLE          0x10000000L  //윈도우를 만들자 마자 화면에 출력한다.
#define WS_DISABLED         0x08000000L  // 사용금지된 상태, 즉 입력을 받아들일 수 없는 상태로 만든다.
#define WS_CLIPSIBLINGS     0x04000000L //차일드끼리 상호 겹친 영역은 그리기 영역에서 제외된다.
#define WS_CLIPCHILDREN     0x02000000L //차일드가 위치한 영역은 그리기 영역에서 제외된다.
#define WS_MAXIMIZE         0x01000000L  // 최초 최대화된 ㅏㅇ태로 윈도우를 만든다.
#define WS_CAPTION          0x00C00000L     /* WS_BORDER | WS_DLGFRAME  */  // 타이틀 바를 가진 윈도우를 만들며 WS_BORDER 스타일을 포함한다.
#define WS_BORDER           0x00800000L  // 단선으로 된 경계선을 만들며 크기 조정은 할 수 없다.
#define WS_DLGFRAME         0x00400000L // 두꺼운 경계선을 가지며 타이틀 바를 가질 수 없다.
#define WS_VSCROLL          0x00200000L  // 수직 스크롤 바를 가진 윈도우를 만든다.
#define WS_HSCROLL          0x00100000L  // 수평 스크롤 바를 가진 윈도우를 만든다.
#define WS_SYSMENU          0x00080000L // 시스템 메뉴를 가진 윈도우를 만든다.
#define WS_THICKFRAME       0x00040000L // 크기 조정 가능한 두꺼운 경계선을 가진다.
#define WS_GROUP            0x00020000L  // 라디오 버튼 등 그룹을 이루는 컨트롤의 그룹 지정에 사용된다.
#define WS_TABSTOP          0x00010000L // Tab키로 포커스를 이동할 수 있다.

#define WS_MINIMIZEBOX      0x00020000L // 최소화 버튼을 만든다.
#define WS_MAXIMIZEBOX      0x00010000L // 최대화 버튼을 만든다.


#define WS_TILED            WS_OVERLAPPED
#define WS_ICONIC           WS_MINIMIZE
#define WS_SIZEBOX          WS_THICKFRAME
#define WS_TILEDWINDOW      WS_OVERLAPPEDWINDOW

/*
 * Common Window Styles
 */
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     | \ /*가장 일반적인 윈도우 스타일*/
                             WS_CAPTION        | \
                             WS_SYSMENU        | \
                             WS_THICKFRAME     | \
                             WS_MINIMIZEBOX    | \
                             WS_MAXIMIZEBOX)

#define WS_POPUPWINDOW      (WS_POPUP          | \  /* 일반적인 팝업 윈도우*/
                             WS_BORDER         | \
                             WS_SYSMENU)

#define WS_CHILDWINDOW      (WS_CHILD)


------------------------------------------------------

이렇게 위와 같이 나와있었다. 오른쪽의 주석 표시는 독자가

책을 보고 일일이 따라 써본것이다^^: 실제 헤더파일은 저렇게 친절하게 한글로

안써있다.. -_-ㅋㅋㅋ


윈도우의 스타일은 서로 중복되어서 줄수 없는 것들이 있는데 그 대표적인 3가지가 아래 3가지 이다.

- 오버랩드

- 차일드

- 팝업


위의 3가지는 서로 겹쳐서 스타일을 줄수가 없다. 만약     WS_CHILD  | WS_POPUP  라고 추면 에러를 발생시킨다.

이유는 상식적으로 생각해봐도 기능적으로 봐도 서로 모순되는 기능들이라서 그렇다..


------------------------------------------------------------------------

[확장 스타일]

 

HWND CreateWindowEx(DWORD dwExSystel, LPCESTR lpClassName, ..............)


CreateWindow 함수에서 끝에 EX가 더붙은 건데 딱 봐도 확장된 이라는 뜻으로 보이며 맞다 -_-ㅋ

CreateWindowEx 함수는 CreateWindow 함수와 다~~~~~ 똑같은데  맨앞의 인자에 딱 하나만 더 추가할 수 있는데

(인자가 딱 하나 더 많다.. 그게 맨 앞에 꺼다..)

CreateWindow에서 지정할수 없는 좀더 고급스러운 스타일 옵션을 줄수 있다고 한다.. -_-ㅋ

그리고  맨앞의 인자가 고급스로운 옵션이라고 했는데 그냥 그 인자를 0 으로 주면 그냥 CreateWindow 함수를 호출하는 것과

동일하다..

사실 우리가 CreateWindow 라고 호출하면 내부에서는 CreateWindowEx함수의 앞에 0으로 넣고 호출하는 거라고 한다.

그러니 우리가 썼던 CreateWindow 함수는 결국 CreateWindowEx 함수의 첫번째 인자 0을 넣고 썼던 것이다. (물론 자동으로 그렇게 해준거지만..)

그 확장 스타일 또한 WinUser.h 라는 헤더 파일에 있는데.. 독자가 한번 열어 봤다. 아래와 같다.. (징그럽게 많다 -_-ㅋㅋ)

 

------------------ WinUser.h 에 있는 확장 윈도우 스타일 정의 ------------------

/*
 * Extended Window Styles
 */
#define WS_EX_DLGMODALFRAME     0x00000001L  // 이중 경계선을 가진 윈도우를 만든다.
#define WS_EX_NOPARENTNOTIFY    0x00000004L  // 생성되거나 파괴될때 부모 윈도우에게 WM_PARENTNOTIFY 메시지를 보내지 않는다.
#define WS_EX_TOPMOST           0x00000008L  // 모든 윈도우보다 수직적으로 위에 있는 윈도우를 만든다.비활성화상태도 다른윈도우에 가려지지 않는다.
#define WS_EX_ACCEPTFILES       0x00000010L  // 드래그 되는 파일을 받을 수 있다.
#define WS_EX_TRANSPARENT       0x00000020L  // 형제 윈도우가 다 그려지기 전에 그려지지 않아 투명하게 보이는 윈도우를 만든다.
#if(WINVER >= 0x0400)
#define WS_EX_MDICHILD          0x00000040L  // MDI 차일드 윈도우를 만든다.
#define WS_EX_TOOLWINDOW        0x00000080L  // 플로팅 툴바 형식의 윈도우를 만든다. 타이틀 바의 높이가 보통윈도우보다 낮으며 작은 폰트를 사용한다.
      // 툴 윈도우는 타스크바에 나타나지 않으며 Alt+Tab 키로 전환 할 수도 없다. 시스템 메뉴 아이콘은 없으나
      // Alt+Space키로 시스템 메뉴는 호출할 수 있다.


#define WS_EX_WINDOWEDGE        0x00000100L  // 양각 모양의 경계선을 가진 윈도우를 만든다.
#define WS_EX_CLIENTEDGE        0x00000200L  // 작업영역이 쑥 들어간 3차원 음각 모양을 만든다.
#define WS_EX_CONTEXTHELP       0x00000400L  // 타이틀바에 ? 버튼을 출력한다. 이 버튼은 도움말 제공에 사용되며 클릭시 커서가 ? 모양으로 바뀌며
      // 차일드를 클릭할 때 WM_HELP 메시지를 보낸다.

#define WS_EX_RIGHT             0x00001000L  // 캡션을 타이틀 바 오른쪽으로 정렬한다.
#define WS_EX_LEFT              0x00000000L  // 캡션을 타이틀 바 왼쪽으로 정렬한다. 이 스타일은 디폴트 이다.
#define WS_EX_RTLREADING        0x00002000L  // 오른쪽에서 왼쪽으로 텍스트를 출력한다. 한국어에는 적용되지 않는 스타일이다.
#define WS_EX_LTRREADING        0x00000000L  // 왼쪽에서 오른쪽으로 텍스트를 정렬한다.
#define WS_EX_LEFTSCROLLBAR     0x00004000L  // 수직 스크롤 바를 작업영역 왼쪽에 배치한다.
#define WS_EX_RIGHTSCROLLBAR    0x00000000L  // 수직 스크롤 바를 작업영역의 오른쪽에 배치한다.이 스타일은 디폴트이다.

#define WS_EX_CONTROLPARENT     0x00010000L  // Tab 키로 차일드 사이를 전환할 수 있다.
#define WS_EX_STATICEDGE        0x00020000L  // 사용자가 입력을 받아들이지 않는다는 의미로 삼차원 장식을 한다.
#define WS_EX_APPWINDOW         0x00040000L  // 윈도우가 보일 때 강제로 타스크 바 위에 있도록 한다.


#define WS_EX_OVERLAPPEDWINDOW  (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE)  // 복합 속성
#define WS_EX_PALETTEWINDOW     (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST) // 복합속성

----------------------------------------------------------------------------------------

 

역시나 옆에 한글로된 주석은 원래 헤더파일에 없고 독자가 책을 보고 쓴것이다. -_-ㅎㅎㅎ


저 많은 스타일을 일일이 다 해보면 좋겠지만  ( 진짜 좋나??? ) 솔직히 의미 정도만 파악하고  실무에서 찾아 쓸수 있으면 된다는

생각을 독자는 갖고 있다. -_-ㅋ 그렇다면 책에서 나온 예제로   몇가지 스타일만 실험 해보자

먼저 CreateWindowEx 함수의 첫번째 인자에 WS_EX_TOPMOST 를 줘서  모든 윈도우의 최상위에 보이게끔 옵션을 줘보자


---------------------------- WS_EX_TOPMOST 옵션을 준 윈도우 예제 ------------------------------


#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("First");  //윈도우 이름 및 타이틀바에 등록할 문자열

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
  HWND hWnd;
  MSG Message;
  WNDCLASS WndClass;
 
  g_hInst = hInstance;

  //------------ 아래 부분은 윈도우 클래스를 설정해주는 것이다. --------------------

  WndClass.cbClsExtra = 0;
  WndClass.cbWndExtra = 0;
  WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  WndClass.hCursor = LoadCursor(NULL,IDC_ARROW);
  WndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
  WndClass.hInstance = hInstance;
  WndClass.lpfnWndProc = WndProc;
  WndClass.lpszClassName = lpszClass;
  WndClass.lpszMenuName = NULL;
  WndClass.style = CS_HREDRAW | CS_VREDRAW;

  //------------ 위 부분은 윈도우 클래스를 설정해주는 것이다. --------------------

  RegisterClass(&WndClass);   //  <-- 여기서는 위에서 설정한 클래스를 등록한다.

  hWnd = CreateWindowEx(WS_EX_TOPMOST,lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
    CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);   // 설정하고 등록한 윈도우를 생성한다.

  ShowWindow(hWnd,nCmdShow);   //생성한 윈도우를 출력..(이 함수를 호출하지않으면 윈도우가 보이지 않는다.)

  while(GetMessage(&Message,NULL,0,0))   //사용자가 종료하기 전까지 반복해서 메세지 처리를 호출한다.
  {
   TranslateMessage(&Message);
   DispatchMessage(&Message);
  }

  return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) //여기서 실제로 메시지를 처리한다.
{
 HDC hdc;
 PAINTSTRUCT ps;
 TCHAR buf[] = "이 윈도우는 WS_EX_TOPMOST 옵션을 줘서 항상 다른윈도우 위에 있다..";

  switch(iMessage)
  {
  case WM_PAINT:
  hdc = BeginPaint(hWnd,&ps);
  TextOut(hdc,10,10,buf,lstrlen(buf));
  EndPaint(hWnd,&ps);
   return 0;

  case WM_DESTROY:
   PostQuitMessage(0);
   return 0;
  }

 return DefWindowProc(hWnd,iMessage,wParam,lParam);  //프로그래머가 처리하지 않은 나머지 동작을 기본처리로 넘긴다.
}


----------------------------------------------------------------------------------------

보는 바와 같이 화면 가장 앞으로 나와있어서 모든 윈도우를 가린다. 의미 그대로 가장 위에 올라와 있는 윈도우를 만든다..

 

 


----------------------------------------------------------------------------------


다음에는 윈도우의 경계선을 바꾸는 경계석 스타일을 확인해보자

스타일 이름뒤에 EDGE 가 붙는 스타일이 경계선 관련 옵션이다. 아래 코드는  총 8개의 윈도우를 차례대로 출력하되

각 경계션 스타일을 다르게하여 한눈에 비교할수 있게 하는 내용이다.  코드를 먼저 보자..


-------------------------- WS_EX 확장스타일 테두리 스타일 예제 ------------------------

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("First");  //윈도우 이름 및 타이틀바에 등록할 문자열

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
  HWND hWnd;
  MSG Message;
  WNDCLASS WndClass;
 
  g_hInst = hInstance;

  //------------ 아래 부분은 윈도우 클래스를 설정해주는 것이다. --------------------

  WndClass.cbClsExtra = 0;
  WndClass.cbWndExtra = 0;
  WndClass.hbrBackground =  (HBRUSH)(COLOR_BTNFACE+1);
  WndClass.hCursor = LoadCursor(NULL,IDC_ARROW);
  WndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
  WndClass.hInstance = hInstance;
  WndClass.lpfnWndProc = WndProc;
  WndClass.lpszClassName = lpszClass;
  WndClass.lpszMenuName = NULL;
  WndClass.style = CS_HREDRAW | CS_VREDRAW;

  //------------ 위 부분은 윈도우 클래스를 설정해주는 것이다. --------------------

  RegisterClass(&WndClass);   //  <-- 여기서는 위에서 설정한 클래스를 등록한다.

  hWnd = CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
    CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);   // 설정하고 등록한 윈도우를 생성한다.

  ShowWindow(hWnd,nCmdShow);   //생성한 윈도우를 출력..(이 함수를 호출하지않으면 윈도우가 보이지 않는다.)

  while(GetMessage(&Message,NULL,0,0))   //사용자가 종료하기 전까지 반복해서 메세지 처리를 호출한다.
  {
   TranslateMessage(&Message);
   DispatchMessage(&Message);
  }

  return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) //여기서 실제로 메시지를 처리한다.
{
  switch(iMessage)
  {
  case WM_CREATE:
  CreateWindow(TEXT("edit"),NULL,WS_CHILD | WS_VISIBLE, 10,10,90,90,hWnd,(HMENU)0,g_hInst,NULL);
  CreateWindowEx(WS_EX_CLIENTEDGE,TEXT("edit"),NULL,WS_CHILD | WS_VISIBLE, 110,10,90,90,hWnd,(HMENU)1,g_hInst,NULL);
  CreateWindowEx(WS_EX_STATICEDGE,TEXT("edit"),NULL,WS_CHILD | WS_VISIBLE, 210,10,90,90,hWnd,(HMENU)2,g_hInst,NULL);
  CreateWindowEx(WS_EX_WINDOWEDGE,TEXT("edit"),NULL,WS_CHILD | WS_VISIBLE, 310,10,90,90,hWnd,(HMENU)3,g_hInst,NULL);

  CreateWindow(TEXT("edit"),NULL,WS_CHILD | WS_VISIBLE | WS_BORDER, 10,110,90,90,hWnd,(HMENU)4,g_hInst,NULL);
  CreateWindowEx(WS_EX_CLIENTEDGE,TEXT("edit"),NULL,WS_CHILD | WS_VISIBLE | WS_BORDER, 110,110,90,90,hWnd,(HMENU)5,g_hInst,NULL);
  CreateWindowEx(WS_EX_STATICEDGE,TEXT("edit"),NULL,WS_CHILD | WS_VISIBLE | WS_BORDER, 210,110,90,90,hWnd,(HMENU)6,g_hInst,NULL);
  CreateWindowEx(WS_EX_WINDOWEDGE,TEXT("edit"),NULL,WS_CHILD | WS_VISIBLE | WS_BORDER, 310,110,90,90,hWnd,(HMENU)7,g_hInst,NULL);
   return 0;

  case WM_DESTROY:
   PostQuitMessage(0);
   return 0;
  }

 return DefWindowProc(hWnd,iMessage,wParam,lParam);  //프로그래머가 처리하지 않은 나머지 동작을 기본처리로 넘긴다.
}


--------------------------------------------------------------------------------------------------------


보시는 바와 같이 8개의 윈도우를 만들었는데

위에 4개와 아래 4개는 완전 똑같은 옵션이다..  다만 아래 4개는 위의 옵션에서 WS_BORDER 이라는 옵션만 추가 했는데

테두리만 진하게 한것인데 위에 두번째와 아래 두번째 윈도우는 WS_BORDER 옵션에 영향을 미치지 않는다.

그것은 의미가없기 때문이다. ( 해당 윈도우 옵션에 위반되기 때문이다.. )

 

'저장소 > VC++' 카테고리의 다른 글

[MFC] DestroyWindow  (0) 2011.11.24
[MFC] MainFrame 크기 고정  (0) 2011.10.21
[MFC] CFileDialog 사용 주의점  (0) 2011.09.23
[Error/Warnning] error LNK2005  (0) 2011.08.16
Visual C++ 컴파일러 버전  (0) 2011.04.29