겸손한 개발을 위한 자양분

함수원형

 

__declspec(naked) LRESULT __stdcall NtUserMessageCall(

    HWND        hwnd,

    UINT        msg,

    WPARAM      wParam,

    LPARAM      lParam,

    ULONG_PTR   xParam,

    DWORD       xpfnProc,

    BOOL        bAnsi )

 

NtUserMessageCall … SendMessage 에 해당하는 시스템 서비스던가…? 기억력 감퇴;;

 

어찌되었든, NtUserMessageCall 에서의 메시지 처리는 xpfnProc 인자를 통해 이뤄집니다.

해당 인자는 Message를 처리해야 하는 win32k 의 처리 procedure 를 가리킵니다.

 

 

확인을 해보면,

가령 NtUserMessageCall 을 호출하는 RealDefWindowProcWorker 의 경우

.text:77D7AEB2 loc_77D7AEB2:                           ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)-81C1j

.text:77D7AEB2                                         ; RealDefWindowProcWorker(x,x,x,x,x)+B2C9j ...

.text:77D7AEB2                 push    [ebp+lpMultiByteStr]

.text:77D7AEB5                 push    2B0h         // FNID_SENDMESSAGEEX

.text:77D7AEBA                 push    0

.text:77D7AEBC                 push    0

.text:77D7AEBE                 push    [ebp+hMem]

.text:77D7AEC1                 push    128h

.text:77D7AEC6

.text:77D7AEC6 loc_77D7AEC6:                           ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)-81CAj

.text:77D7AEC6                                         ; RealDefWindowProcWorker(x,x,x,x,x)+3029Fj

.text:77D7AEC6                 push    ebx

.text:77D7AEC7                 jmp     loc_77D4C756

 

.text:77D4C756 loc_77D4C756:                           ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)+2FE07j

.text:77D4C756                 call    ds:_gapfnScSendMessage ; NtUserMessageCall(x,x,x,x,x,x,x)

xpfnProc 0x2B0h

 

.text:77D4B2A5 loc_77D4B2A5:                           ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)+38j

.text:77D4B2A5                 cmp     edi, 400h

.text:77D4B2AB                 push    [ebp+lpMultiByteStr] ; int

.text:77D4B2AE                 push    29Eh          // FNID_DEFWINDOWPROC

.text:77D4B2B3                 push    0               ; int

.text:77D4B2B5                 push    [ebp+hMem]      ; hMem

.text:77D4B2B8                 push    dword ptr [ebp+WideCharStr] ; int

.text:77D4B2BB                 push    edi             ; int

.text:77D4B2BC                 push    eax             ; int

.text:77D4B2BD                 jnb     loc_77D7AB10

.text:77D4B2C3                 xor     ecx, ecx

.text:77D4B2C5                 mov     cl, ds:_MessageTable[edi]

.text:77D4B2CB                 and     ecx, 3Fh        ; int

.text:77D4B2CE                 call    ds:_gapfnScSendMessage[ecx*4] ; NtUserMessageCall(x,x,x,x,x,x,x)

xpfnProc 0x29Eh

 

위의 두 부분에서 NtUserMessageCall 을 호출하고 있으며,

이때, NtUserMessageCall 에서는 이를 다음과 같이 처리합니다.

bf834b50 8b4d1c          mov     ecx,dword ptr [ebp+1Ch] // xpfnProc

bf834b53 83c106          add     ecx,6

bf834b56 83e11f          and     ecx,1Fh

bf834b59 ff7518          push    dword ptr [ebp+18h]

bf834b5c 50              push    eax

bf834b5d ff7510          push    dword ptr [ebp+10h]

bf834b60 ff750c          push    dword ptr [ebp+0Ch]

bf834b63 ff7508          push    dword ptr [ebp+8]

bf834b66 a158859abf      mov     eax,dword ptr [win32k!gpsi (bf9a8558)]

bf834b6b ff54880c        call    dword ptr [eax+ecx*4+0Ch]

 

위의 어셈 코드에서, 호출되는 procedure 의 주소를 보면,

bc5d0650  00200031

bc5d0654  00000000

bc5d0658  00000155

bc5d065c  bf90ade2 win32k!xxxWrapSBWnd16Proc

bc5d0660  bf80f420 win32k!xxxWrapRealDefWindowProc

bc5d0664  bf86a712 win32k!xxxWrapMenuWindowProc

bc5d0668  bf915448 win32k!xxxWrapDesktopWndProc

bc5d066c  bf80f420 win32k!xxxWrapRealDefWindowProc    >> (29E+6) & 1F

bc5d0670  bf80f420 win32k!xxxWrapRealDefWindowProc

bc5d0674  bf8cb6f2 win32k!xxxWrapSwitchWndProc

bc5d0678  bf942a7c win32k!xxxUnusedFunctionId

bc5d067c  bf942a7c win32k!xxxUnusedFunctionId

bc5d0680  bf942a7c win32k!xxxUnusedFunctionId

bc5d0684  bf942a7c win32k!xxxUnusedFunctionId

bc5d0688  bf942a7c win32k!xxxUnusedFunctionId

bc5d068c  bf942a7c win32k!xxxUnusedFunctionId

bc5d0690  bf942a7c win32k!xxxUnusedFunctionId

bc5d0694  bf942a7c win32k!xxxUnusedFunctionId

bc5d0698  bf942a7c win32k!xxxUnusedFunctionId

bc5d069c  bf90b699 win32k!fnHkINLPCWPEXSTRUCT

bc5d06a0  bf92f155 win32k!fnHkINLPCWPRETEXSTRUCT

bc5d06a4  bf942a7c win32k!xxxUnusedFunctionId

bc5d06a8  bf942a7c win32k!xxxUnusedFunctionId

bc5d06ac  bf942a7c win32k!xxxUnusedFunctionId

bc5d06b0  bf942a7c win32k!xxxUnusedFunctionId

bc5d06b4  bf831785 win32k!xxxWrapSendMessage          >> (2B0+6) & 1F

bc5d06b8  bf8a003f win32k!xxxSendMessageFF

bc5d06bc  bf82eedc win32k!xxxSendMessageEx

bc5d06c0  bf89ef23 win32k!xxxWrapCallWindowProc

bc5d06c4  bf8622d9 win32k!xxxWrapSendMessageBSM

bc5d06c8  bf942a7c win32k!xxxUnusedFunctionId

bc5d06cc  bf942a7c win32k!xxxUnusedFunctionId

bc5d06d0  bf82f3dd win32k!xxxWrapSendNotifyMessage

bc5d06d4  bf82f461 win32k!xxxWrapSendMessageCallback

bc5d06d8  bf942a7c win32k!xxxUnusedFunctionId

bc5d06dc  bf90a41b win32k!xxxSBWndProc

bc5d06e0  bf80d027 win32k!xxxDefWindowProc

bc5d06e4  bf865f56 win32k!xxxMenuWindowProc

bc5d06e8  bf87fac4 win32k!xxxDesktopWndProc

bc5d06ec  bf80d027 win32k!xxxDefWindowProc

bc5d06f0  bf80d027 win32k!xxxDefWindowProc

 

위와 같이 메시지를 처리하는 실제 procedure 들의 주소가 담긴 테이블을 확인할 수 있으며,

RealDefWindowProcWorker 가 호출하는 0x2B0, 0x29E 인자에 대응하는 실제 procedure 를 찾을 수 있습니다.

 

다음은 xpfnProc에 대응하는 FNID 값입니다.

#define FNID_START                  0x0000029A

#define FNID_WNDPROCSTART           0x0000029A

 

#define FNID_SCROLLBAR              0x0000029A      // xxxSBWndProc;

#define FNID_ICONTITLE              0x0000029B      // xxxDefWindowProc;

#define FNID_MENU                   0x0000029C      // xxxMenuWindowProc;

#define FNID_DESKTOP                0x0000029D      // xxxDesktopWndProc;

#define FNID_DEFWINDOWPROC          0x0000029E      // xxxDefWindowProc;

 

#define FNID_WNDPROCEND             0x0000029E      // see PatchThreadWindows

#define FNID_CONTROLSTART           0x0000029F

 

#define FNID_BUTTON                 0x0000029F      // No server side proc

#define FNID_COMBOBOX               0x000002A0      // No server side proc

#define FNID_COMBOLISTBOX           0x000002A1      // No server side proc

#define FNID_DIALOG                 0x000002A2      // No server side proc

#define FNID_EDIT                   0x000002A3      // No server side proc

#define FNID_LISTBOX                0x000002A4      // No server side proc

#define FNID_MDICLIENT              0x000002A5      // No server side proc

#define FNID_STATIC                 0x000002A6      // No server side proc

 

#define FNID_IME                    0x000002A7      // No server side proc

#define FNID_CONTROLEND             0x000002A7

 

#define FNID_HKINLPCWPEXSTRUCT      0x000002A8

#define FNID_HKINLPCWPRETEXSTRUCT   0x000002A9

#define FNID_DEFFRAMEPROC           0x000002AA      // No server side proc

#define FNID_DEFMDICHILDPROC        0x000002AB      // No server side proc

#define FNID_MB_DLGPROC             0x000002AC      // No server side proc

#define FNID_MDIACTIVATEDLGPROC     0x000002AD      // No server side proc

#define FNID_SENDMESSAGE            0x000002AE

 

#define FNID_SENDMESSAGEFF          0x000002AF

#define FNID_SENDMESSAGEEX          0x000002B0

#define FNID_CALLWINDOWPROC         0x000002B1

#define FNID_SENDMESSAGEBSM         0x000002B2

#define FNID_SWITCH                 0x000002B3      // Just used by GetTopMostInserAfter

#define FNID_TOOLTIP                0x000002B4

#define FNID_END                    0x000002B4

http://msdn.microsoft.com/en-us/library/bb773173(VS.85).aspx

Windows Controls

A control is a child window that an application uses in conjunction with another window to enable user interaction. Controls are most often used within dialog boxes, but they can also be used in other windows. Controls within dialog boxes provide the user with a way to type text, choose options, and initiate actions. Controls in other windows provide a variety of services, such as letting the user choose commands, view status, and view and edit text.

The common controls overview documentation describes the common controls delivered in Microsoft Windows and the programming elements used to create and manipulate them.

The following table lists the Windows controls.

Control

Description

Animation

A window that displays an Audio-Video Interleaved (AVI) clip.

Button

Notifies the parent window when the user selects the control.

Combo Box

A combination of a list box and an edit control, enabling the user to select or add items.

ComboBoxEx

An extension of the combo box control that provides native support for item images.

Date and Time Picker

A simple and intuitive interface through which to exchange date and time information with a user.

Drag List Box

A type of list box that enables the user to drag items from one position to another.

Edit

A window within the user can view and edit text.

Flat Scroll Bar

A scroll bar with a more customizable appearance than standard scroll bars.

Header

A window that is usually positioned above columns of text or numbers. It contains a title for each column, and it can be divided into parts.

Hot Key

A window that enables the user to enter a combination of keystrokes to be used as a hot key.

Image Lists

A collection of images of the same size, each of which can be referred to by its index.

IP Address

A window in which the user can enter an Internet Protocol (IP) address in an easily understood format.

List Box

A simple list from which the user can select one or more items.

List-View

A list box that provides several ways to arrange and display the items.

Month Calendar

A calendar that enables the user to select a date or dates.

Pager

A set of arrow buttons that enable the contents of a control window to be scrolled.

Progress Bar

An animated control that indicates the progress of a lengthy operation.

Property Sheet

A dialog box that enables the user to view and edit the properties of an item. Pages may be viewed as tabs, or in succession as a wizard.

ReBar

A container for child windows. An application assigns child windows, which are often other controls, to a rebar control band.

Rich Edit

A window in which the user can view and edit text with character and paragraph formatting. It can also contain embedded COM objects.

Scroll Bar

A control that enables the user to choose the direction and distance to scroll information in a related window.

Static

Non-interactive text, including labels for other controls.

Status Bar

A horizontal window at the bottom of a parent window in which an application can display various kinds of status information.

SysLink

A hypertext link.

Tab

A selectable page, analogous to a divider in a notebook. By using a tab control, an application can define multiple pages for the same area of a window or dialog box.

Task Dialog

A more powerful alternative to simple message boxes, incorporating elements such as custom buttons, radio buttons, hyperlinks, and progress bars.

Toolbar

A window that contains one or more buttons and possibly other controls.

ToolTip

A message that appears automatically when the mouse pointer hovers over a tool.

Trackbar

A slider with optional tick marks, used to set a value within a range.

Tree-View

A hierarchical list of items, such as the headings in a document or the files and directories on a disk.

Up-Down

A pair of arrow buttons that the user can click to increment or decrement a value, such as a scroll position or a number displayed in a companion control.

 

http://msdn.microsoft.com/en-us/library/ms632595(VS.85).aspx


WM_ACTIVATEAPP

The WM_ACTIVATEAPP message is sent when a window belonging to a different application than the active window is about to be activated. The message is sent to the application whose window is being activated and to the application whose window is being deactivated.

A window receives this message through its WindowProc function.

WM_CANCELMODE

The WM_CANCELMODE message is sent to cancel certain modes, such as mouse capture. For example, the system sends this message to the active window when a dialog box or message box is displayed. Certain functions also send this message explicitly to the specified window regardless of whether it is the active window. For example, the EnableWindow function sends this message when disabling the specified window.

A window receives this message through its WindowProc function.

WM_CHILDACTIVATE

The WM_CHILDACTIVATE message is sent to a child window when the user clicks the window's title bar or when the window is activated, moved, or sized.

A window receives this message through its WindowProc function.

WM_CLOSE

The WM_CLOSE message is sent as a signal that a window or an application should terminate.

A window receives this message through its WindowProc function.

WM_COMPACTING

The WM_COMPACTING message is sent to all top-level windows when the system detects more than 12.5 percent of system time over a 30- to 60-second interval is being spent compacting memory. This indicates that system memory is low.

A window receives this message through its WindowProc function.

Note  This message is provided only for compatibility with 16-bit Windows-based applications.

WM_CREATE

The WM_CREATE message is sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. (The message is sent before the function returns.) The window procedure of the new window receives this message after the window is created, but before the window becomes visible.

A window receives this message through its WindowProc function.

WM_DESTROY

The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window procedure of the window being destroyed after the window is removed from the screen.

This message is sent first to the window being destroyed and then to the child windows (if any) as they are destroyed. During the processing of the message, it can be assumed that all child windows still exist.

A window receives this message through its WindowProc function.

WM_ENABLE

The WM_ENABLE message is sent when an application changes the enabled state of a window. It is sent to the window whose enabled state is changing. This message is sent before the EnableWindow function returns, but after the enabled state (WS_DISABLED style bit) of the window has changed.

A window receives this message through its WindowProc function.

WM_ENTERSIZEMOVE

The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving or sizing modal loop. The window enters the moving or sizing modal loop when the user clicks the window's title bar or sizing border, or when the window passes the WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the message specifies the SC_MOVE or SC_SIZE value. The operation is complete when DefWindowProc returns.

The system sends the WM_ENTERSIZEMOVE message regardless of whether the dragging of full windows is enabled.

A window receives this message through its WindowProc function.

WM_EXITSIZEMOVE

The WM_EXITSIZEMOVE message is sent one time to a window, after it has exited the moving or sizing modal loop. The window enters the moving or sizing modal loop when the user clicks the window's title bar or sizing border, or when the window passes the WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the message specifies the SC_MOVE or SC_SIZE value. The operation is complete when DefWindowProc returns.

A window receives this message through its WindowProc function.

WM_GETICON

The WM_GETICON message is sent to a window to retrieve a handle to the large or small icon associated with a window. The system displays the large icon in the ALT+TAB dialog, and the small icon in the window caption.

A window receives this message through its WindowProc function.

WM_GETMINMAXINFO

The WM_GETMINMAXINFO message is sent to a window when the size or position of the window is about to change. An application can use this message to override the window's default maximized size and position, or its default minimum or maximum tracking size.

A window receives this message through its WindowProc function.

WM_INPUTLANGCHANGE

The WM_INPUTLANGCHANGE message is sent to the topmost affected window after an application's input language has been changed. You should make any application-specific settings and pass the message to the DefWindowProc function, which passes the message to all first-level child windows. These child windows can pass the message to DefWindowProc to have it pass the message to their child windows, and so on.

A window receives this message through its WindowProc function.

WM_INPUTLANGCHANGEREQUEST

The WM_INPUTLANGCHANGEREQUEST message is posted to the window with the focus when the user chooses a new input language, either with the hotkey (specified in the Keyboard control panel application) or from the indicator on the system taskbar. An application can accept the change by passing the message to the DefWindowProc function or reject the change (and prevent it from taking place) by returning immediately.

A window receives this message through its WindowProc function.

WM_MOVE

The WM_MOVE message is sent after a window has been moved.

A window receives this message through its WindowProc function.

WM_MOVING

The WM_MOVING message is sent to a window that the user is moving. By processing this message, an application can monitor the position of the drag rectangle and, if needed, change its position.

A window receives this message through its WindowProc function.

WM_NCACTIVATE

The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed to indicate an active or inactive state.

A window receives this message through its WindowProc function.

WM_NCCALCSIZE

The WM_NCCALCSIZE message is sent when the size and position of a window's client area must be calculated. By processing this message, an application can control the content of the window's client area when the size or position of the window changes.

A window receives this message through its WindowProc function.

WM_NCCREATE

The WM_NCCREATE message is sent prior to the WM_CREATE message when a window is first created.

A window receives this message through its WindowProc function.

WM_NCDESTROY

The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY message. WM_DESTROY is used to free the allocated memory object associated with the window.

The WM_NCDESTROY message is sent after the child windows have been destroyed. In contrast, WM_DESTROY is sent before the child windows are destroyed.

A window receives this message through its WindowProc function.

WM_NULL

The WM_NULL message performs no operation. An application sends the WM_NULL message if it wants to post a message that the recipient window will ignore.

A window receives this message through its WindowProc function.

WM_PARENTNOTIFY

The WM_PARENTNOTIFY message is sent to the parent of a child window when the child window is created or destroyed, or when the user clicks a mouse button while the cursor is over the child window. When the child window is being created, the system sends WM_PARENTNOTIFY just before the CreateWindow or CreateWindowEx function that creates the window returns. When the child window is being destroyed, the system sends the message before any processing to destroy the window takes place.

A window receives this message through its WindowProc function.

WM_QUERYDRAGICON

The WM_QUERYDRAGICON message is sent to a minimized (iconic) window. The window is about to be dragged by the user but does not have an icon defined for its class. An application can return a handle to an icon or cursor. The system displays this cursor or icon while the user drags the icon.

A window receives this message through its WindowProc function.

WM_QUERYOPEN

The WM_QUERYOPEN message is sent to an icon when the user requests that the window be restored to its previous size and position.

A window receives this message through its WindowProc function.

WM_SHOWWINDOW

The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown.

A window receives this message through its WindowProc function.

WM_SIZE

The WM_SIZE message is sent to a window after its size has changed.

A window receives this message through its WindowProc function.

WM_SIZING

The WM_SIZING message is sent to a window that the user is resizing. By processing this message, an application can monitor the size and position of the drag rectangle and, if needed, change its size or position.

A window receives this message through its WindowProc function.

WM_STYLECHANGED

The WM_STYLECHANGED message is sent to a window after the SetWindowLong function has changed one or more of the window's styles.

A window receives this message through its WindowProc function.

WM_STYLECHANGING

The WM_STYLECHANGING message is sent to a window when the SetWindowLong function is about to change one or more of the window's styles.

A window receives this message through its WindowProc function.

WM_THEMECHANGED

The WM_THEMECHANGED message is broadcast to every window following a theme change event. Examples of theme change events are the activation of a theme, the deactivation of a theme, or a transition from one theme to another.

WM_USERCHANGED

The WM_USERCHANGED message is sent to all windows after the user has logged on or off. When the user logs on or off, the system updates the user-specific settings. The system sends this message immediately after updating the settings.

A window receives this message through its WindowProc function.

WM_WINDOWPOSCHANGED

The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place in the Z order has changed as a result of a call to the SetWindowPos function or another window-management function.

A window receives this message through its WindowProc function.

WM_WINDOWPOSCHANGING

The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in the Z order is about to change as a result of a call to the SetWindowPos function or another window-management function.

A window receives this message through its WindowProc function.

윈도우 스타일

MSDN2009. 2. 18. 11:31

/* 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  */
#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

#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)

/* 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  // 툴바 윈도우
#define WS_EX_WINDOWEDGE        0x00000100L  // 양각 윈도우
#define WS_EX_CLIENTEDGE        0x00000200L  // 음각 윈도우
#define WS_EX_CONTEXTHELP       0x00000400L  // 타이틀바에 ? 버튼 출력

#endif /* WINVER >= 0x0400 */
#if(WINVER >= 0x0400)

#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)

#endif /* WINVER >= 0x0400 */

#if(_WIN32_WINNT >= 0x0500)
#define WS_EX_LAYERED           0x00080000

#endif /* _WIN32_WINNT >= 0x0500 */

#if(WINVER >= 0x0500)
#define WS_EX_NOINHERITLAYOUT   0x00100000L // Disable inheritence of mirroring by children
#define WS_EX_LAYOUTRTL         0x00400000L // Right to left mirroring
#endif /* WINVER >= 0x0500 */

#if(_WIN32_WINNT >= 0x0501)
#define WS_EX_COMPOSITED        0x02000000L
#endif /* _WIN32_WINNT >= 0x0501 */
#if(_WIN32_WINNT >= 0x0500)
#define WS_EX_NOACTIVATE        0x08000000L
#endif /* _WIN32_WINNT >= 0x0500 */