- Windows Template Library
- ½ÃÀÛÇϱâ
- ¼³Ä¡
- ¸µÅ©
- ÆÁ
- ¸®½ºÆ®ºä ÄÁÆ®·Ñ Full Row Select Äѱâ
- ¸ð´Þ ´ÙÀ̾ó·Î±× ÄÁÆ®·Ñ ¸®»çÀÌ¡
- ClientEdge ±×¸®±â
- Contained Window
- ´õºí ¹öÆÛ¸µ
- IDLE ó¸®
- Custom Modal Dialog
- DDX
- ¸Þ´º ¾÷µ¥ÀÌÆ®
- ´ÜÃàŰ
- RichEdit ÄÁÆ®·Ñ »ç¿ëÇϱâ
- ´Ù¿î·Îµå
1 Windows Template Library
http://sourceforge.net/projects/wtl/
À©µµ¿ìÁî ¾ÖÇø®ÄÉÀÌ¼Ç ¹× UI ÄÄÆ÷³ÍÆ® °³¹ßÀ» À§ÇÑ C++ ¶óÀ̺귯¸®. ATLÀ» ±â¹ÝÀ¸·Î °³¹ßµÇ¾úÀ¸¸ç, °¢Á¾ ÄÁÆ®·Ñ, ´ëÈâ, À©µµ¿ì ÇÁ·¹ÀÓ, GDI ¿ÀºêÁ§Æ® µîÀ» Á¦°øÇÑ´Ù.
API·Î GUI ÇÁ·Î±×·¡¹ÖÇÏ·Á´Ï ±ÍÂú°í, MFC¸¦ ¾²ÀÚ´Ï ÀÇÁ¸¼ºÀÌ Â¥Áõ³ª´Â °æ¿ì, ´ë¾ÈÀ¸·Î »ç¿ëÇÒ ¼ö ÀÖ´Ù. ÅÛÇø´ ±â¹ÝÀ¸·Î ÀÛ¼ºµÇ¾ú°í, Ưº°ÇÑ DLL °°Àº °ÍÀ» ÇÊ¿ä·Î ÇÏÁö ¾Ê´Â´Ù. ¹®Á¦´Â °ü·Ã ¹®¼°¡ ³Ê¹« ºÎÁ·ÇÏ´Ù´Â °ÍÀÌ´Ù. °ø½ÄÀûÀÎ ÇïÇÁ ÆÄÀϵµ Á¸ÀçÇÏÁö ¾Ê°í, ÀÎÅͳݿ¡ ÀÖ´Â ¹®¼µéµµ MFC °°Àº °Í¿¡ ºñÇÏ¸é °ÅÀÇ ¾ø´Â °Í°ú ¸¶Âù°¡Áö´Ù.
Àå´ÜÁ¡À» ¿ä¾àÇØ º¸ÀÚ¸é ´ÙÀ½°ú °°´Ù.
from
http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=18197
I built a couple of medium sized GUI apps with WTL.
My experience was generally positive, but I had been using ATL for at least four years by that point, and considered something of an expert in it. With that background, WTL was a breath of fresh air to me compared to the MFC prison.
The plus side of WTL:
- Designed like ATL rather than MFC. Functionality is composed via multiple inheritance in a shallow hierarchy rather than using a deep single-inheritance hierarchy where the functionality you want isn't in the branch you need it (What do you mean I need a view to have scrolling support?)
- All source code is available, and it's quite readable if you understand ATL. This also alleviates the "end of life" arguments - who cares if it doesn't get maintained? You've got the source code, and it's easy to tweak.
- Since WTL is built around composition, it's dirt simple to extend to do whatever you need to.
- Support from WTL's author is quite good - there's a WTL yahoo group that he hangs out on.
Down sides of WTL:
- If you don't know ATL, or are afraid of templates, stay away. It won't make any sense at all.
- Documentation is essentially non-existant. There's a good intro article (2 parts) on http://www.develop.com somewhere that explains the basics of what's in the library and how to use it. http://www.codeproject.com has a WTL section with some good stuff. But there's no books and no printed articles and no likelyhood of any appearing any time soon.
- Very slow compile times. Lots of templates mean lots of work for the compiler.
In general, WTL is the expert's tool. If you know Win32 programming well, and understand how ATL is put together, WTL will make you VERY productive, even without the handholding of wizards. If you aren't, well, you're in for a bit of a tough road. But the destination is well worth it.
On the other hand, if you just want to churn out a couple of dialogs, use WinForms instead.
2 ½ÃÀÛÇϱâ
2.1 ¼³Ä¡
- ¶óÀ̺귯¸® À̸§ÀÌ ¸»ÇØÁÖµíÀÌ "template" ¶óÀ̺귯¸®À̱⠶§¹®¿¡ Çì´õ ÆÄÀϸ¸ ÀÖÀ¸¸é ¸¸»ç OK´Ù. ¹èÆ÷º»À» ´Ù¿î·Îµå¹Þ¾Æ Àû´çÇÑ °÷¿¡´Ù ¾ÐÃàÀ» Ǭ ´ÙÀ½, Visual C++ > Tools -> Option À¸·Î °¡¼ include µð·ºÅ丮¸¦ ¼³Á¤ÇØ ÁÖ¸é ³¡ÀÌ´Ù.
- À§Àڵ带 Ãß°¡Çϱâ À§Çؼ´Â ¹èÆ÷º» ¾ÐÃà Ǭ °÷¿¡ °¡º¸¸é appwiz ¶ó´Â µð·ºÅ丮°¡ ÀÖÀ» °ÍÀÌ´Ù. ±× ¾È¿¡ ÀÖ´Â ½ºÅ©¸³Æ® ÆÄÀÏ(setupXX.js)À» ÇØ´çÇÏ´Â Visual C++ ¹öÀü¿¡ ¸ÂÃç¼ ½ÇÇàÇÏ¸é ³¡.
2.2 ¸µÅ©
-
http://sourceforge.net/projects/wtl/
-
GameDev.net > Using the Windows Template Library Part 1
-
GameDev.net > Using the Windows Template Library Part 2
-
http://www.codeproject.com/wtl/
-
WTL for MFC Programmers, Part I - ATL GUI Classes
-
WTL for MFC Programmers, Part II - WTL GUI Base Classes
-
WTL for MFC Programmers, Part III - Toolbars and Status Bars
-
WTL for MFC Programmers, Part IV - Dialogs and Controls
-
WTL for MFC Programmers, Part V - Advanced Dialog UI Classes
-
WTL for MFC Programmers, Part VI - Hosting ActiveX Controls
-
WTL for MFC Programmers, Part VII - Splitter Windows
-
WTL for MFC Programmers, Part VIII - Property Sheets and Wizards
-
WTL for MFC Programmers, Part IX - GDI Classes, Common Dialogs, and Utility Classes
-
The Joys of WTL
-
http://www.viksoe.dk/code/wtldoc.htm
7.5 ±âÁØÀÇ ¹®¼¸¦ ZIP ÆÄÀÏ·Î ´Ù¿î·Îµå¹ÞÀ» ¼ö ÀÖ´Ù. ¾ÆÁ÷ ÀÛ¾÷ÀÌ ÁøÇàÁß.
3 ÆÁ
3.1 ¸®½ºÆ®ºä ÄÁÆ®·Ñ Full Row Select Äѱâ
myListCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
API¸¦ ¸ð¸£´Ï ¿ø...
3.2 ¸ð´Þ ´ÙÀ̾ó·Î±× ÄÁÆ®·Ñ ¸®»çÀÌ¡
class cMainDialog : public CDialogImpl<cMainDialog>,
public CDialogResize<cMainDialog> // !!!
{
...
BEGIN_MSG_MAP_EX(cMainDialog)
MSG_WM_INITDIALOG(OnInitDialog)
...
CHAIN_MSG_MAP(CDialogResize<cMainDialog>) // !!!
END_MSG_MAP()
// !!!
BEGIN_DLGRESIZE_MAP(cMainDialog)
DLGRESIZE_CONTROL(IDC_GEOMETRY_GROUP, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_LEVEL_EDIT, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_LEVEL_BUTTON, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_GEOMETRY_EDIT, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_GEOMETRY_BUTTON, DLSZ_MOVE_X)
END_DLGRESIZE_MAP()
LRESULT OnInitDialog(HWND hwndFocus, LPARAM lParam)
{
...
DlgResize_Init(true, true, WS_THICKFRAME); // !!!
...
}
};
3.3 ClientEdge ±×¸®±â
µüÈ÷ ATL/WTL °ú °ü·ÃµÈ °Íµµ ¾Æ´Ï°í, À©µµ¿ì »ý¼ºÇÒ ¶§ WS_EX_CLIENTEDGE Ç÷¡±× ÁÖ¸é ±×¸¸ÀÎ ³»¿ëÀÌÁö¸¸...
CRect client, tmp;
GetClientRect(&client);
CBrush light, face, shadow, black;
light.CreateSolidBrush(::GetSysColor(COLOR_BTNHIGHLIGHT));
face.CreateSolidBrush(::GetSysColor(COLOR_BTNFACE));
shadow.CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
black.CreateSolidBrush(::GetSysColor(COLOR_3DDKSHADOW));
// top
tmp.SetRect(client.left, client.top, client.right - 1, client.top + 1);
dc.FillRect(tmp, shadow);
tmp.SetRect(client.left, client.top + 1, client.right - 1, client.top + 2);
dc.FillRect(tmp, black);
// bottom
tmp.SetRect(client.left, client.bottom - 2, client.right - 1, client.bottom - 1);
dc.FillRect(tmp, face);
tmp.SetRect(client.left, client.bottom - 1, client.right - 1, client.bottom - 0);
dc.FillRect(tmp, light);
// left
tmp.SetRect(client.left, client.top + 1, client.left + 1, client.bottom - 1);
dc.FillRect(tmp, shadow);
tmp.SetRect(client.left + 1, client.top + 1, client.left + 2, client.bottom - 2);
dc.FillRect(tmp, black);
// right
tmp.SetRect(client.right - 2, client.top + 1, client.right - 1, client.bottom - 2);
dc.FillRect(tmp, face);
//tmp.SetRect(client.right - 2, client.top + 1, client.right - 1, client.bottom - 2);
//dc.FillRect(tmp, shadow);
// center
tmp.SetRect(client.left + 2, client.top + 2, client.right - 2, client.bottom - 2);
dc.FillSolidRect(tmp, ::GetSysColor(COLOR_APPWORKSPACE));
3.4 Contained Window
class cMainWindow : public cWindowImpl<...>
{
private:
CContainedWindowT<CEdit> m_Edit;
public:
BEGIN_MSG_MAP(cMainWindow)
...
ALT_MSG_MAP(1)
MESSAGE_HANDLER(WM_CHAR, OnEditChar)
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
...
if (!m_Edit.Create(this, 1, m_hWnd, rcDefault))
return -1;
...
}
LRESULT OnEditChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
...
}
}; ¸Þ½ÃÁö¸Ê ID¿¡ ÁÖÀÇ
3.5 ´õºí ¹öÆÛ¸µ
CDoubleBufferImpl Ŭ·¡½º¸¦ »ó¼Ó¹ÞÀ¸¸é µÈ´Ù. ±×·±µ¥ ¾à°£ ÀÌ»óÇÑ°Ô CDoubleBufferImpl Ŭ·¡½º ³»ºÎ¿¡ OnPaint ÇÔ¼ö¿Í ¸Þ½ÃÁö¸ÊÀÌ Á¤Àǰ¡ µÇ¾îÀִµ¥, OnPaint ÇÔ¼ö°¡ Á¦´ë·Î È£ÃâµÇÁö ¾Ê´Â´Ù. ±×·¯¹Ç·Î ½ÇÁ¦ »ó¼Ó¹ÞÀº Ŭ·¡½º¿¡¼ Çѹø ¼±¾ðÇØÁØ´Ù.
class cMainDialog : public CDialogImpl<cMainDialog>,
public CDoubleBufferImpl<cMainDialog>
{
public:
enum { IDD = IDD_MAIN };
BEGIN_MSG_MAP_EX(cMainDialog)
...
MESSAGE_HANDLER(WM_PAINT, OnPaint) // ¸Þ½ÃÁö¸ÊÀº Á¤ÀÇÇϵÇ, ½ÇÁ¦ ÇÔ¼ö´Â ¼±¾ðÇÏÁö ¾Ê¾Æ¾ßÇÑ´Ù.
...
END_MSG_MAP()
void DoPaint(CDCHandle dc)
{
// ¿©±â¼ ¹º°¡¸¦ ½ÇÁ¦·Î ±×·ÁÁØ´Ù.
...
}
};
3.6 IDLE ó¸®
CIdleHandler Ŭ·¡½º´Â ±âº»ÀûÀ¸·Î idle 󸮸¦ Çѹø ÇÑ ÈÄ¿¡´Â WM_MOUSEMOVE, WM_PAINT ÀÌ¿ÜÀÇ ¸Þ½ÃÁö°¡ µµÂøÇؾ߸¸ ´Ù½Ã idle 󸮸¦ ÇÑ´Ù. Ç×»ó idle 󸮸¦ ÇÏ°Ô ¸¸µé±â À§Çؼ´Â Ŭ·¡½º¸¦ »ó¼Ó¹Þ´Â °ÍÀÌ ÆíÇÏ´Ù.
class cMainFrame : public CFrameWindowImpl<cMainFrame>,
public CUpdateUI<cMainFrame>,
public CMessageFilter,
public CIdleHandler
{
...
virtual BOOL OnIdle()
{
// ¿©±â¼ ÇÒ ÀÏÀ» Á¤ÀÇÇÑ´Ù.
return TRUE; // º° ÀÇ¹Ì ¾ø´Ù.
}
...
};
class cCustomMessageLoop : public CMessageLoop
{
public:
virtual BOOL OnIdle(int nIdleCount)
{
CMessageLoop::OnIdle(nIdleCount);
// ¸®ÅϰªÀÌ Áß¿äÇÏ´Ù! CMessageLoop::OnIdle ÇÔ¼ö´Â ±âº»ÀûÀ¸·Î FALSE¸¦ ¹ÝȯÇÑ´Ù.
return TRUE;
}
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
cCustomMessageLoop theLoop;
cMainFrame theWindow;
theModule.Init(NULL, hInstance);
theModule.AddMessageLoop(&theLoop);
....
return 0;
}
3.7 Custom Modal Dialog
CDialogImpl Ŭ·¡½º¸¦ »ó¼Ó¹ÞÀº ¸ð´Þ Dialog¸¦ ¸¸µç °æ¿ì, Dialog ¼Ó¼º â¿¡¼ StyleÀ» PopupÀ¸·Î ÇØÁà¾ß Á¤»óÀûÀ¸·Î µ¿ÀÛÇÑ´Ù.
3.8 DDX
DDX_FLOAT ¸ÅÅ©·Î¸¦ »ç¿ëÇϱâ À§Çؼ´Â atlddx.h ÆÄÀÏÀ» includeÇϱâ Àü¿¡ _ATL_USE_DDX_FLOAT ¸ÅÅ©·Î¸¦ Á¤ÀÇÇØÁà¾ßÇÑ´Ù.
3.9 ¸Þ´º ¾÷µ¥ÀÌÆ®
¸Þ´º ¾÷µ¥ÀÌÆ®(Ȱ¼ºÈ/ºñȰ¼ºÈ, üũ µî)¸¦ »ç¿ëÇϱâ À§Çؼ´Â CUpdateUI¸¦ »ó¼Ó¹ÞÀº ´ÙÀ½, BEGIN_UPDATE_UI_MAP, END_UPDATE_UI_MAP ¸ÊÀ» Á¤ÀÇÇØÁà¾ßÇÑ´Ù. ½ÇÁ¦ ¾÷µ¥ÀÌÆ®´Â UIEnable, UISetCheck µîÀÇ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.
class cMainFrame : public CFrameWindowImpl<cMainFrame>,
public CUpdateUI<cMainFrame>,
public CMessageFilter,
public CIdleHandler
{
BEGIN_UPDATE_UI_MAP(cMainFrame)
UPDATE_ELEMENT(ID_VIEW_ORIGINALMESH, UPDUI_MENUPOPUP)
UPDATE_ELEMENT(ID_VIEW_NAVIGATIONMESH, UPDUI_MENUPOPUP)
UPDATE_ELEMENT(ID_VIEW_WIREFRAME, UPDUI_MENUPOPUP)
UPDATE_ELEMENT(ID_VIEW_BODY, UPDUI_MENUPOPUP)
END_UPDATE_UI_MAP()
};
3.10 ´ÜÃàŰ
- ´ÜÃà۸¦ Áö¿øÇϱâ À§Çؼ´Â CMessageFilter¸¦ »ó¼Ó¹Þ°í, PreTranslateMessage ÇÔ¼ö¸¦ ¿À¹ö¶óÀ̵åÇØÁØ ´ÙÀ½, À©µµ¿ì »ý¼º ½Ã¿¡ AddMessageFilter ÇÔ¼ö¸¦ ÀÌ¿ëÇØ ¸Þ½ÃÁö ·çÇÁ¿¡´Ù ÇÊÅ͸¦ Ãß°¡ÇؾßÇÑ´Ù.
3.11 RichEdit ÄÁÆ®·Ñ »ç¿ëÇϱâ
RichEdit ÄÁÆ®·ÑÀ» »ç¿ëÇϱâ À§Çؼ´Â ´ÙÀ½°ú °°Àº ¸ÅÅ©·Î¸¦ atlctrls.h ÆÄÀÏÀ» include Çϱâ Àü¿¡ Á¤ÀÇÇϰí, ¾îµò°¡¿¡¼ ¶óÀ̺귯¸®¸¦ Á÷Á¢ ·ÎµåÇØÁà¾ßÇÑ´Ù.
// RichEdit 1.0À» »ç¿ëÇϱâ À§ÇÑ Á¤ÀÇ
//#define WINVER 0x0400
//#define _WIN32_IE 0x0400
//#define _RICHEDIT_VER 0x0100
// RichEdit 2.0À» »ç¿ëÇϱâ À§ÇÑ Á¤ÀÇ
#define WINVER 0x0500
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0501
#define _RICHEDIT_VER 0x0200
#include <atlctrls.h>
...
HINSTANCE hInstRich = ::LoadLibrary(CRichEditCtrl::GetLibraryName());
ATLASSERT(hInstRich != NULL);
...
::FreeLibrary(hInstRich);
4 ´Ù¿î·Îµå
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)