[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 |