성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 그냥 RSS Reader 기능과 약간의 UI 편의성 때문에 사용...
[이종효] 오래된 소프트웨어는 보안 위협이 되기도 합니다. 혹시 어떤 기능...
[정성태] @Keystroke IEEE의 문서를 소개해 주시다니... +_...
[손민수 (Keystroke)] 괜히 듀얼채널 구성할 때 한번에 같은 제품 사라고 하는 것이 아...
[정성태] 전각(Full-width)/반각(Half-width) 기능을 토...
[정성태] Vector에 대한 내용은 없습니다. Vector가 닷넷 BCL...
[orion] 글 읽고 찾아보니 디자인 타임에는 InitializeCompon...
[orion] 연휴 전에 재현 프로젝트 올리자 생각해 놓고 여의치 않아서 못 ...
[정성태] 아래의 글에 정리했으니 참고하세요. C# - Typed D...
[정성태] 간단한 재현 프로젝트라도 있을까요? 저런 식으로 설명만 해...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Win32 - 리소스에 포함된 대화창 Template의 2진 코드 해석 방법</h1> <p> 이번에는 다음의 글로 시작하는 시리즈 6개를 제 맘대로 정리해 봤습니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The evolution of dialog templates – Introduction ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040617-00/?p=38833'>https://devblogs.microsoft.com/oldnewthing/20040617-00/?p=38833</a> </pre> <br /> <hr style='width: 50%' /><br /> <br /> 비주얼 스튜디오로 기본 생성한 C/C++ 윈도우 프로젝트를 보면 텍스트 형식의 RC 파일이 하나 들어 있고, 그 안에 IDD_ABOUTBOX 대화창으로 식별되는 텍스트가 추가돼 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About Project1" FONT 8, "MS Shell Dlg" BEGIN <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20231025-00/?p=108925'>ICON</a> IDR_MAINFRAME,IDC_STATIC,14,14,21,20 LTEXT "Project1, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX LTEXT "Copyright (c) 2023",IDC_STATIC,42,26,114,8 DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP END </pre> <br /> C# 세대에게 설명하자면, "폼 디자이너"의 초기 모델이라고 보면 될 듯합니다. ^^ 실제로 Visual studio는 위의 대화창 템플릿을 읽어들여 다음과 같이 디자인 창을 띄워 사용자가 컨트롤을 쉽게 추가/삭제/배치할 수 있도록 돕습니다.<br /> <br /> <img alt='dialog_template_part1_1.png' src='/SysWebRes/bbs/dialog_template_part1_1.png' /><br /> <br /> 단지 C# Windows Forms 프로젝트의 경우에는 디자인 창의 내용을 C# 코드로 직렬화하는 반면, 위의 dialog template 파일은 Win32 리소스 문법에 따라 직렬화한다는 차이가 있는 정도입니다.<br /> <br /> 실제로 여러분은 Resource Compiler(rc.exe)를 이용해 위의 dialog template만을 담은 파일을 컴파일할 수 있습니다. 이를 위해 필요한 include와 상수를 정의하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um\Windows.h" #define IDD_ABOUTBOX 103 #define IDR_MAINFRAME 128 #ifndef IDC_STATIC #define IDC_STATIC -1 #endif IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About Project1" FONT 8, "MS Shell Dlg" BEGIN ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20 LTEXT "Project1, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX LTEXT "Copyright (c) 2023",IDC_STATIC,42,26,114,8 DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP END </pre> <br /> Visual Studio 명령행 창에서 다음과 같이 명령을 내리면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > c:\temp> <span style='color: blue; font-weight: bold'>rc test.rc</span> Microsoft (R) Windows (R) Resource Compiler Version 10.0.10011.16384 Copyright (C) Microsoft Corporation. All rights reserved. </pre> <br /> 그럼, 결과 파일로 res 확장자를 가진 이진 파일이 생성됩니다. <br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 00 00 00 00 20 00 00 00 FF FF 00 00 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 34 01 00 00 20 00 00 00 FF FF 05 00 FF FF 67 00 00 00 00 00 30 10 09 04 00 00 00 00 00 00 00 00 01 00 FF FF 00 00 00 00 00 00 00 00 C8 00 C8 80 04 00 00 00 00 00 AA 00 3E 00 00 00 00 00 41 00 62 00 6F 00 75 00 74 00 20 00 50 00 72 00 6F 00 6A 00 65 00 63 00 74 00 31 00 00 00 08 00 00 00 ...[생략]... 29 00 20 00 32 00 30 00 32 00 33 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 03 50 71 00 29 00 32 00 0E 00 01 00 00 00 FF FF 80 00 4F 00 4B 00 00 00 00 00 </pre> <a name='read_res'></a> <br /> 비주얼 스튜디오로 C/C++ Windows 응용 프로그램을 빌드하면 저 res 2진 파일을 EXE/DLL 바이너리에 추가합니다. 그리고 다시 코드에서는 저 내용 중 원하는 대화상자, 이번 글에서는 IDD_ABOUTBOX 식별자로 구분되는 리소스의 내용을 이렇게 추출할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > HRSRC hrsrc = ::<a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-findresourcea'>FindResource</a>(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), RT_DIALOG); HGLOBAL hglobal = ::<a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadresource'>LoadResource</a>(hInst, hrsrc); LPVOID lpv = ::<a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-lockresource'>LockResource</a>(hglobal); DWORD resSize = <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-sizeofresource'>SizeofResource</a>(hInst, hrsrc); BYTE* pBuffer = (BYTE*)lpv; wchar_t buffer[1024] = { 0 }; for (int i = 1; i <= resSize; i++) { wsprintf(buffer, L"%02X ", pBuffer[i - 1]); OutputDebugString(buffer); if (i % 16 == 0) { OutputDebugString(L"\n"); } } ::<a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freeresource'>FreeResource</a>(hglobal); </pre> <br /> 출력 내용은 우리가 컴파일했던 test.res의 5번째 줄부터 해당하는 바이트가 동일하게 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 01 00 FF FF 00 00 00 00 00 00 00 00 C8 00 C8 80 04 00 00 00 00 00 AA 00 3E 00 00 00 00 00 41 00 62 00 6F 00 75 00 74 00 20 00 50 00 72 00 6F 00 6A 00 65 00 63 00 74 00 31 00 00 00 08 00 00 00 00 01 4D 00 53 00 20 00 53 00 68 00 65 00 6C 00 6C 00 20 00 44 00 6C 00 67 00 00 00 00 00 00 00 00 00 00 00 03 00 00 50 0E 00 0E 00 15 00 14 00 FF FF FF FF FF FF 82 00 FF FF 80 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 02 50 2A 00 0E 00 72 00 08 00 FF FF FF FF FF FF 82 00 50 00 72 00 6F 00 6A 00 65 00 63 00 74 00 31 00 2C 00 20 00 56 00 65 00 72 00 73 00 69 00 6F 00 6E 00 20 00 31 00 2E 00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 50 2A 00 1A 00 72 00 08 00 FF FF FF FF FF FF 82 00 43 00 6F 00 70 00 79 00 72 00 69 00 67 00 68 00 74 00 20 00 28 00 63 00 29 00 20 00 32 00 30 00 32 00 33 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 03 50 71 00 29 00 32 00 0E 00 01 00 00 00 FF FF 80 00 4F 00 4B 00 00 00 00 00 </pre> <br /> 그리고 위의 2진 파일의 내용을 해석하는 방법을 시리즈의 2~5번째 글에서 소개합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The evolution of dialog templates – 16-bit Classic Templates ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040618-00/?p=38803'>https://devblogs.microsoft.com/oldnewthing/20040618-00/?p=38803</a> The evolution of dialog templates – 16-bit Extended Templates ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040622-00/?p=38773'>https://devblogs.microsoft.com/oldnewthing/20040622-00/?p=38773</a> The evolution of dialog templates – 32-bit Classic Templates ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040621-00/?p=38793'>https://devblogs.microsoft.com/oldnewthing/20040621-00/?p=38793</a> The evolution of dialog templates – 32-bit Extended Templates ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040623-00/?p=38753'>https://devblogs.microsoft.com/oldnewthing/20040623-00/?p=38753</a> </pre> <br /> 버전별로 4개의 dialog template이 제공되는데 이 관계를 아래의 그림에서 잘 나타내고 있습니다.<br /> <br /> <img alt='dialog_template_part1_2.png' src='/SysWebRes/bbs/dialog_template_part1_2.png' /><br /> <br /> 16비트 포맷에 해당하는 DIALOG는 Windows 1.0 시절에, 16비트 DIALOGEX는 Windows 95와 후속 버전만 지원합니다. 그리고 각각의 버전이 다시 32비트 포맷으로 포팅됐습니다. 아주 오래된 프로그램이 아니라면 현재 32-bit DIALOGEX 이외의 형식은 구경조차 힘들 것입니다.<br /> <br /> 따라서, 예전 버전의 해석 방식은 각각 "<a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040618-00/?p=38803'>The evolution of dialog templates – 16-bit Classic Templates</a>", "<a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040622-00/?p=38773'>The evolution of dialog templates – 16-bit Extended Templates</a>", "<a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040621-00/?p=38793'>The evolution of dialog templates – 32-bit Classic Templates</a>" 글에서 설명하고 있으니 참고하시고, 이번 글에서는 위의 예제로 나온 바이너리를 해석해야 하므로 "<a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040623-00/?p=38753'>32-bit Extended Templates</a>"을 기준으로 설명합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 대화창의 헤더(32-bit extended header)는 다음과 같은 구조체로 시작한다고 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > WORD wDlgVer; // version number - always 1 WORD wSignature; // always 0xFFFF DWORD dwHelpID; // help ID DWORD dwExStyle; // window extended style DWORD dwStyle; // dialog style WORD cItems; // number of controls in this dialog, 즉 대화창 1개에 65,535개까지의 컨트롤을 담을 수 있음 WORD x; // x-coordinate WORD y; // y-coordinate WORD cx; // width WORD cy; // height </pre> <br /> 이 글의 예제에서 사용한 리소스의 경우에는 각각 다음과 같은 정보로 연결될 수 있고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > wDlgVer == 1 wSignature == 0xffff dwHelpID == 0 dwExStyle == 0 dwStyle == DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU == 2160591048 == 80 C8 00 C8 cItems == BEGIN/END 사이의 컨트롤 수 == ICON/LTEXT/LTEXT/DEFPUSHBUTTON 총 4개 x == 0 y == 0 cx == 170 (0xaa) cy == 62 (0x3e) </pre> <br /> 실제로 위의 바이트를 LockResource로 구한 바이트 배열에서 찾을 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 01 00 FF FF 00 00 00 00 00 00 00 00 C8 00 C8 80 04 00 : 컨트롤 수 00 00 : x 00 00 : y AA 00 : cx 3E 00 : cy </pre> <br /> 그다음은 3개의 문자열 정보가 나오는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 00 00: menu name 문자열 또는 ordinal 00 00: class name 문자열 41 00 62 00 6F 00 75 00 74 00 20 00 50 00 72 00 6F 00 6A 00 65 00 63 00 74 00 31 00 00 00: CAPTION 문자열 "About Project1" </pre> <br /> 해당 값이 문자열(위의 경우 "About Project1")인 경우라면 UNICODE 값과 함께 끝을 알리는 null 문자(\0\0)가 나옵니다. 반면 ordinal로 표현된다면 0xff, 0x00이 먼저 나오고 이어서 ordinal 2바이트가 나온다고 합니다. 예를 들어 위에서 menu name의 ordinal 값이 "2A 00"이라면 다음의 4바이트가 기록되는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > FF 00 2A 00 </pre> <br /> 어쨌든 위의 예제에서는 menu와 class name에 할당된 문자열이 없기 때문에 널 종료 문자(\0\0)만이 있습니다. (참고로 <a target='tab' href='https://www.sysnet.pe.kr/2/0/13285#src'>대화창의 class name 지정은 지난 예제에서 설명</a>한 적이 있습니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그다음은 가변 항목이 나오는데요, 대화창의 STYLE에,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > STYLE <span style='color: blue; font-weight: bold'>DS_SETFONT</span> | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About Project1" <span style='color: blue; font-weight: bold'>FONT 8, "MS Shell Dlg"</span> </pre> <br /> 위와 같이 DS_SETFONT가 설정돼 있다면 함께 명시한 FONT 정보가 나온다고 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > WORD wPoint; // point size WORD wWeight; // font weight BYTE bItalic; // 1 if italic, 0 if not BYTE bCharSet; // character set WCHAR szFontName[]; // variable-length </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 08 00: point size 00 00: font weight (0x0000 == FW_DONTCARE) 00: 1 if italic, 0 if not 01: character set, 0x01 = DEFAULT_CHARSET 4D 00 53 00 20 00 53 00 68 00 65 00 6C 00 6C 00 20 00 44 00 6C 00 67 00 00 00: "MS Shell Dlg" (널 종료 문자 포함) </pre> <br /> 자, 그다음부터는 이제 cItems에 지정한 컨트롤의 수만큼 다음의 정보들이 DWORD(4바이트) 정렬로 나열됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > DWORD dwHelpID; // help identifier DWORD dwExStyle; // window extended style DWORD dwStyle; // window style WORD x; // x-coordinate (DLUs) WORD y; // y-coordinate (DLUs) WORD cx; // width (DLUs) WORD cy; // height (DLUs) DWORD dwID; // control ID, 32비트 값이긴 하지만 <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/menurc/wm-command#remarks'>WM_COMMAND 등의 메시지에서는 여전히 16비트 값으로 다루기</a> 때문에 사실상 16비트만 사용 가능 WCHAR szClassName[];// variable-length (possibly ordinal) WCHAR szText[]; // variable-length (possibly ordinal) WORD cbExtra; // amount of extra data BYTE rgbExtra[cbExtra]; // extra data follows (usually none) </pre> <br /> szClassName, szText, rgbExtra 때문에 크기가 가변적이므로 고정 레코드로 읽어들일 수 없다는 점이 귀찮군요. 그래도 4개밖에 없으니 ^^ 아래와 같이 정리해 봤습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 00 00 00 00: dwHelpID 00 00 00 00: dwExStyle 03 00 00 50: window style, 0x50000003, 아마도 WS_CHILD(0x40000000) | WS_VISIBLE(0x10000000) | SS_ICON (0x03) 0E 00: x (14) 0E 00: y (14) 15 00: cx (21) 14 00: cy (20) FF FF FF FF: control ID (-1) FF FF 82 00: szClass == ordinal 0x0082 == static FF FF 80 00: szText == ordinal 0x0080 00 00: cbExtra 00 00: 위의 cbExtra가 0이므로 이후 rgbExtra 바이트 배열이 아님. 4바이트 정렬이므로 padding 바이트 </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 00 00 00 00: dwHelpID 00 00 00 00: dwExStyle 80 00 02 50: window style, 0x50020080, 아마도 WS_GROUP(0x020000) | WS_CHILD(0x40000000) | WS_VISIBLE(0x10000000) | SS_NOPREFIX(0x80) 2A 00: x (42) 0E 00: y (14) 72 00: cx (114) 08 00: cy (8) FF FF FF FF: control ID (-1) FF FF 82 00: szClass == ordinal 0x0082 == static 50 00 72 00 6F 00 6A 00 65 00 63 00 74 00 31 00 2C 00 20 00 56 00 65 00 72 00 73 00 69 00 6F 00 6E 00 20 00 31 00 2E 00 30 00 00 00: "Project1, Version 1.0" 문자열 00 00: cbExtra 00 00: 위의 cbExtra가 0이므로 이후 rgbExtra 바이트 배열이 아님. 4바이트 정렬이므로 padding 바이트 </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 00 00 00 00: dwHelpID 00 00 00 00: dwExStyle 00 00 02 50: window style, 0x50020000, 아마도 WS_GROUP(0x020000) | WS_CHILD(0x40000000) | WS_VISIBLE(0x10000000) 2A 00: x (42) 1A 00: y (26) 72 00: cx (114) 08 00: cy (8) FF FF FF FF: control ID (-1) FF FF 82 00: szClass == ordinal 0x0082 == static 43 00 6F 00 70 00 79 00 72 00 69 00 67 00 68 00 74 00 20 00 28 00 63 00 29 00 20 00 32 00 30 00 32 00 33 00 00 00: "Copyright (c) 2023" 00 00: cbExtra </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 00 00 00 00: dwHelpID 00 00 00 00: dwExStyle 01 00 03 50: window style, 0x50030001, 아마도 WS_GROUP(0x020000) | WS_TABSTOP(0x010000) | WS_CHILD(0x40000000) | WS_VISIBLE(0x10000000) | BS_DEFPUSHBUTTON(0x01) 71 00: x (113) 29 00: y (41) 32 00: cx (50) 0E 00: cy (14) 01 00 00 00: control ID == IDOK(0x01) FF FF 80 00: szClass == ordinal 0x0080 == button 4F 00 4B 00: "OK" 00 00: cbExtra 00 00: 위의 cbExtra가 0이므로 이후 rgbExtra 바이트 배열이 아님. 4바이트 정렬이므로 padding 바이트 </pre> <br /> 그러니까 결국, <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dialogboxa'>DialogBox</a> 등의 함수들은 res로 컴파일된 바이너리에서 리소스 ID에 해당하는 대화창 정보를 위와 같은 포맷에 따라 해석해 CreateWindow로 보여주는 것입니다. 좀 ^^ 대단하지 않나요?<br /> <br /> 게다가... 이런 작업들이 Windows 1.0 시절부터 Win32 API와 그에 따른 Visual C++ 초기 IDE 도구가 협업해 대화창에 대한 Form 디자이너를 제공하고 있었다는 것은 매우 혁신적인 아이디어가 아니었을까 싶습니다. 제가 리눅스는 잘 몰라서 확실히 언급할 수는 없지만 아마 제대로 된 폼 디자이너를 아직도 갖추지 못한 것에 비하면 1985년에 이런 생각을 했다는 것에 놀랍기까지 합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이렇게 해서 olenewthing의 6개 글 중 5개를 정리했습니다. 나머지 하나는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The evolution of dialog templates – Summary ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040624-00/?p=38733'>https://devblogs.microsoft.com/oldnewthing/20040624-00/?p=38733</a> </pre> <br /> 총정리를 다음의 표 하나로 제시하고 있습니다.<br /> <br /> <img alt='dialog_template_part1_3.png' src='/SysWebRes/bbs/dialog_template_part1_3.png' /><br /> <br /> 즉, 4개의 DIALOG Template 버전이 있지만 16비트/32비트에 대한 차이와 약간의 필드 추가 등을 제외하면 거의 비슷합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 약간의 첨언을 하자면.<br /> <br /> 대화창에 포함할 수 있는 컨트롤의 수가 WORD 2바이트로 제한이 되는데요, 사실 이건 제약이라고 볼 수 없습니다. 왜냐하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Why is the limit of window handles per process 10,000? ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20070718-00/?p=25963'>https://devblogs.microsoft.com/oldnewthing/20070718-00/?p=25963</a> </pre> <br /> 프로세스 하나가 생성할 수 있는 User Object가 10,000개로 제한이 되기 때문에 Dialog Template의 제약은 오히려 현재로서는 가능성이 없는 수준입니다.<br /> <br /> 또한, 위에서 설명한 dialog 포맷에 해당하는 구조체가 winuser.h 헤더 파일에 정의돼 있는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > DLGTEMPLATE structure (winuser.h) ; <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgtemplate'>https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgtemplate</a> /* * <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040621-00/?p=38793'>original NT 32 bit dialog template</a>: */ typedef struct { DWORD style; DWORD dwExtendedStyle; WORD cdit; short x; short y; short cx; short cy; } DLGTEMPLATE; </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > DLGITEMTEMPLATE structure (winuser.h) ; <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgitemtemplate'>https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgitemtemplate</a> /* * <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20040621-00/?p=38793'>32 bit Dialog item template</a>. */ typedef struct { DWORD style; DWORD dwExtendedStyle; short x; short y; short cx; short cy; WORD id; } DLGITEMTEMPLATE; </pre> <br /> 아쉽게도 이 글에서 설명한 "32-bit Extended Templates" 유형이 아닌 "32-bit Classic Templates"에 해당하니 유의할 필요가 있습니다.<br /> <a name='class_ordinal'></a> <br /> 마지막으로, 본문에서 컨트롤들의 클래스에 대한 ordinal id를 설명 없이 언급했지만, 기본적인 컨트롤은 다음의 내용으로 <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgitemtemplate#remarks'>문서</a>에 나와 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0x0080 Button 0x0081 Edit 0x0082 Static 0x0083 List box 0x0084 Scroll bar 0x0085 Combo box </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1759
(왼쪽의 숫자를 입력해야 합니다.)