성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
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 C/C++ - 대화창 템플릿을 런타임에 코딩해서 사용</h1> <p> 지난 글에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Win32 - 리소스에 포함된 대화창 Template의 2진 코드 해석 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/13286'>https://www.sysnet.pe.kr/2/0/13286</a> </pre> <br /> rc 파일로 컴파일된 대화창 Template의 2진 코드를 해석하는 방법을 알아봤는데요, 그렇다면 거꾸로 적절한 2진 코드만 만들 수 있다면 대화창이 되는 것과 다를 바가 없습니다. 뭐랄까, <a target='tab' href='https://www.sysnet.pe.kr/2/0/10889'>어셈블리 코드만 맞춰주면 함수로 호출할 수 있는 것과 유사</a>한데요, 바로 아래의 글에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Building a dialog template at run-time ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20050429-00/?p=35743'>https://devblogs.microsoft.com/oldnewthing/20050429-00/?p=35743</a> </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;' > // <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20050429-00/?p=35743'>https://devblogs.microsoft.com/oldnewthing/20050429-00/?p=35743</a> class DialogTemplate { public: LPCDLGTEMPLATE Template() { return (LPCDLGTEMPLATE)&v[0]; } void AlignToDword() { if (v.size() % 4) Write(NULL, 4 - (v.size() % 4)); } void Write(LPCVOID pvWrite, DWORD cbWrite) { v.insert(v.end(), cbWrite, 0); if (pvWrite) CopyMemory(&v[v.size() - cbWrite], pvWrite, cbWrite); } template<typename T> void Write(T t) { Write(&t, sizeof(T)); } void WriteString(LPCWSTR psz) { Write(psz, (lstrlenW(psz) + 1) * sizeof(WCHAR)); } private: vector<BYTE> v; }; </pre> <br /> 이후 "<a target='tab' href='https://www.sysnet.pe.kr/2/0/13286'>Win32 - 리소스에 포함된 대화창 Template의 2진 코드 해석 방법</a>" 글에서 설명한 포맷에 따라 2진 코드를 써주면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > BOOL FakeMessageBox(HWND hwnd, LPCWSTR pszMessage, LPCWSTR pszTitle) { BOOL fSuccess = FALSE; HDC hdc = GetDC(NULL); if (hdc) { NONCLIENTMETRICSW ncm = { sizeof(ncm) }; if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) { <span style='color: blue; font-weight: bold'>DialogTemplate tmp;</span> // Write out the extended dialog template header tmp.Write<WORD>(1); // dialog version tmp.Write<WORD>(0xFFFF); // extended dialog template tmp.Write<DWORD>(0); // help ID tmp.Write<DWORD>(0); // extended style tmp.Write<DWORD>(WS_CAPTION | WS_SYSMENU | DS_SETFONT | DS_MODALFRAME); tmp.Write<WORD>(2); // number of controls tmp.Write<WORD>(32); // X tmp.Write<WORD>(32); // Y tmp.Write<WORD>(200); // width tmp.Write<WORD>(80); // height tmp.WriteString(L""); // no menu tmp.WriteString(L""); // default dialog class tmp.WriteString(pszTitle); // title // Next comes the font description. // See text for discussion of fancy formula. // 참고: <a target='tab' href='https://www.sysnet.pe.kr/2/0/13288'>Win32 - 대화창의 DLU 단위를 pixel로 변경하는 방법</a> <span style='color: blue; font-weight: bold'>if (ncm.lfMessageFont.lfHeight < 0) { ncm.lfMessageFont.lfHeight = -MulDiv(ncm.lfMessageFont.lfHeight, 72, GetDeviceCaps(hdc, LOGPIXELSY)); }</span> tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfHeight); // point tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfWeight); // weight tmp.Write<BYTE>(ncm.lfMessageFont.lfItalic); // Italic tmp.Write<BYTE>(ncm.lfMessageFont.lfCharSet); // CharSet tmp.WriteString(ncm.lfMessageFont.lfFaceName); // Then come the two controls. First is the static text. tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE); // style tmp.Write<WORD>(7); // x tmp.Write<WORD>(7); // y tmp.Write<WORD>(200 - 14); // width tmp.Write<WORD>(80 - 7 - 14 - 7); // height tmp.Write<DWORD>(-1); // control ID tmp.Write<DWORD>(0x0082FFFF); // static tmp.WriteString(pszMessage); // text tmp.Write<WORD>(0); // no extra data // Second control is the OK button. tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON); // style tmp.Write<WORD>(75); // x tmp.Write<WORD>(80 - 7 - 14); // y tmp.Write<WORD>(50); // width tmp.Write<WORD>(14); // height tmp.Write<DWORD>(IDCANCEL); // control ID tmp.Write<DWORD>(0x0080FFFF); // static tmp.WriteString(L"OK"); // text tmp.Write<WORD>(0); // no extra data // Template is ready - go display it. <span style='color: blue; font-weight: bold'>fSuccess = DialogBoxIndirect(hInst, tmp.Template(), hwnd, AboutModal) >= 0;</span> } ReleaseDC(NULL, hdc); // fixed 11 May } return fSuccess; } </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;' > case WM_CHAR: if (wParam == ' ') { FakeMessageBox(hWnd, L"This is the text of a dynamically-generated dialog template. " L"If Raymond had more time, this dialog would have looked prettier.", L"Title of message box"); } break; </pre> <br /> 이렇게 대화창이 뜨는 것을 볼 수 있습니다.<br /> <br /> <img alt='runtime_dialog_template_1.png' src='/SysWebRes/bbs/runtime_dialog_template_1.png' /><br /> <br /> 물론, 그동안 만들었던,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Win32 C/C++ - 직접 띄운 대화창 템플릿을 위한 Modal 메시지 루프 생성 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/13329'>https://www.sysnet.pe.kr/2/0/13329</a> </pre> <br /> DLGTEMPLATEEX::ReadDialog를 이용해 동일한 template 바이너리를 읽어 대화창을 보여줄 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > BOOL FakeMessageBox(HWND hwnd, LPCWSTR pszMessage, LPCWSTR pszTitle) { BOOL fSuccess = FALSE; HDC hdc = GetDC(NULL); if (hdc) { NONCLIENTMETRICSW ncm = { sizeof(ncm) }; if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) { DialogTemplate tmp; // Write out the extended dialog template header ...[생략]... <span style='color: blue; font-weight: bold'>// fSuccess = DialogBoxIndirect(hInst, tmp.Template(), hwnd, AboutModal) >= 0; ShowMyDialogWindow(hwnd, (LPVOID)tmp.Template(), AboutModeless);</span> } ReleaseDC(NULL, hdc); // fixed 11 May } return fSuccess; } void ShowMyDialogWindow(HWND hWnd, LPVOID lpv, DLGPROC dlgProc) { // EndDialog는 메시지 루프를 빠져나오지 않는 문제가 있는데 // 이를 해결하기 위해서는 별도의 EndManualModalDialog 식의 사용자 정의 종료 함수를 만들어야 함! // DLGTEMPLATEEX* item = DLGTEMPLATEEX::ReadDialog(hInst, hWnd, AboutModal, lpv); DLGTEMPLATEEX* item = DLGTEMPLATEEX::ReadDialog(hInst, hWnd, dlgProc, lpv); item->ApplyDsStyle(); item->LoadMenu(); item->LoadFont(); item->DLUtoPixel(); if (item->Create() == FALSE) { delete item; } item->DoModal(); } void ShowMyDialogWindow(HWND hWnd) { HRSRC hrsrc = ::FindResource(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), RT_DIALOG); if (hrsrc == nullptr) { return; } HGLOBAL hglobal = ::LoadResource(hInst, hrsrc); if (hglobal == nullptr) { return; } LPVOID lpv = ::LockResource(hglobal); DWORD resSize = SizeofResource(hInst, hrsrc); ShowMyDialogWindow(hWnd, lpv, AboutModeless); ::FreeResource(hglobal); } </pre> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=2077&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 마지막으로 RC Compiler와 C Compiler가 유사하면서도 다른 2가지 흥미 있는 이야기가 있으니 시간 나시면 한번 읽어보세요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The Resource Compiler’s preprocessor is not the same as the C preprocessor ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20171004-00/?p=97126'>https://devblogs.microsoft.com/oldnewthing/20171004-00/?p=97126</a> What is the expression language used by the Resource Compiler for non-preprocessor expressions? ; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20230313-00/?p=107928'>https://devblogs.microsoft.com/oldnewthing/20230313-00/?p=107928</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1203
(왼쪽의 숫자를 입력해야 합니다.)