OSDN Git Service

2012/01/19 23:57:20
authorqwerty2501 <riot313@gmail.com>
Thu, 19 Jan 2012 14:57:20 +0000 (23:57 +0900)
committerqwerty2501 <riot313@gmail.com>
Thu, 19 Jan 2012 14:57:20 +0000 (23:57 +0900)
282 files changed:
include/WTL/AppWiz/Files/Templates/1033/AboutDlg.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/AboutDlg.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/ChildFrm.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/ChildFrm.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/Frame.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/Frame.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/MainDlg.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/MainDlg.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/View.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/View.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/resource.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/root.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/root.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/root.ico [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/rootDoc.ico [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/rootidl.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/stdafx.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/stdafx.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1033/toolbar.bmp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/AboutDlg.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/AboutDlg.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/ChildFrm.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/ChildFrm.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/Frame.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/Frame.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/MainDlg.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/MainDlg.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/View.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/View.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/resource.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/root.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/root.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/root.ico [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/rootDoc.ico [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/rootidl.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/stdafx.cpp [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/stdafx.h [new file with mode: 0644]
include/WTL/AppWiz/Files/Templates/1041/toolbar.bmp [new file with mode: 0644]
include/WTL/AppWiz/Files/WTLAppWiz.ico [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/AboutDlg.cpp [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/AboutDlg.h [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/Frame.cpp [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/Frame.h [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/MainDlg.cpp [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/MainDlg.h [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/View.cpp [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/View.h [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/resource.h [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/root.cpp [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/root.h [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/root.ico [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/rootidl.h [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/stdafx.cpp [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/stdafx.h [new file with mode: 0644]
include/WTL/AppWizCE/Files/Templates/1033/toolbar.bmp [new file with mode: 0644]
include/WTL/AppWizCE/Files/WTLAppWizCE.ico [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/AboutDlg.cpp [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/AboutDlg.h [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/Frame.cpp [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/Frame.h [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/MainDlg.cpp [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/MainDlg.h [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/View.cpp [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/View.h [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/resource.h [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/root.cpp [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/root.ico [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/stdafx.cpp [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/stdafx.h [new file with mode: 0644]
include/WTL/AppWizMobile/Files/Templates/1033/toolbar.bmp [new file with mode: 0644]
include/WTL/AppWizMobile/Files/WTLMobile.ico [new file with mode: 0644]
include/WTL/Include/atlapp.h [new file with mode: 0644]
include/WTL/Include/atlcrack.h [new file with mode: 0644]
include/WTL/Include/atlctrls.h [new file with mode: 0644]
include/WTL/Include/atlctrlw.h [new file with mode: 0644]
include/WTL/Include/atlctrlx.h [new file with mode: 0644]
include/WTL/Include/atlddx.h [new file with mode: 0644]
include/WTL/Include/atldlgs.h [new file with mode: 0644]
include/WTL/Include/atldwm.h [new file with mode: 0644]
include/WTL/Include/atlfind.h [new file with mode: 0644]
include/WTL/Include/atlframe.h [new file with mode: 0644]
include/WTL/Include/atlgdi.h [new file with mode: 0644]
include/WTL/Include/atlmisc.h [new file with mode: 0644]
include/WTL/Include/atlprint.h [new file with mode: 0644]
include/WTL/Include/atlres.h [new file with mode: 0644]
include/WTL/Include/atlresce.h [new file with mode: 0644]
include/WTL/Include/atlscrl.h [new file with mode: 0644]
include/WTL/Include/atlsplit.h [new file with mode: 0644]
include/WTL/Include/atltheme.h [new file with mode: 0644]
include/WTL/Include/atluser.h [new file with mode: 0644]
include/WTL/Include/atlwince.h [new file with mode: 0644]
include/WTL/Include/atlwinx.h [new file with mode: 0644]
include/WTL/Samples/Aero/AboutDlg.h [new file with mode: 0644]
include/WTL/Samples/Aero/Aero.cpp [new file with mode: 0644]
include/WTL/Samples/Aero/Aero.h [new file with mode: 0644]
include/WTL/Samples/Aero/Aero.sln [new file with mode: 0644]
include/WTL/Samples/Aero/AeroView.h [new file with mode: 0644]
include/WTL/Samples/Aero/MainFrm.h [new file with mode: 0644]
include/WTL/Samples/Aero/res/Aero.ico [new file with mode: 0644]
include/WTL/Samples/Aero/res/toolbar.bmp [new file with mode: 0644]
include/WTL/Samples/Aero/resource.h [new file with mode: 0644]
include/WTL/Samples/Aero/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/Aero/stdafx.h [new file with mode: 0644]
include/WTL/Samples/Alpha/Alpha.cpp [new file with mode: 0644]
include/WTL/Samples/Alpha/Alpha.h [new file with mode: 0644]
include/WTL/Samples/Alpha/Alpha.sln [new file with mode: 0644]
include/WTL/Samples/Alpha/Alpha.suo [new file with mode: 0644]
include/WTL/Samples/Alpha/Alpha.vcxproj [new file with mode: 0644]
include/WTL/Samples/Alpha/Alpha.vcxproj.filters [new file with mode: 0644]
include/WTL/Samples/Alpha/Alpha.vcxproj.user [new file with mode: 0644]
include/WTL/Samples/Alpha/aboutdlg.h [new file with mode: 0644]
include/WTL/Samples/Alpha/mainfrm.h [new file with mode: 0644]
include/WTL/Samples/Alpha/readme.txt [new file with mode: 0644]
include/WTL/Samples/Alpha/res/Alpha.ico [new file with mode: 0644]
include/WTL/Samples/Alpha/res/toolbar.bmp [new file with mode: 0644]
include/WTL/Samples/Alpha/res/toolbar_old.bmp [new file with mode: 0644]
include/WTL/Samples/Alpha/resource.h [new file with mode: 0644]
include/WTL/Samples/Alpha/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/Alpha/stdafx.h [new file with mode: 0644]
include/WTL/Samples/Alpha/view.h [new file with mode: 0644]
include/WTL/Samples/BmpView/BmpView.cpp [new file with mode: 0644]
include/WTL/Samples/BmpView/BmpView.sln [new file with mode: 0644]
include/WTL/Samples/BmpView/BmpView.suo [new file with mode: 0644]
include/WTL/Samples/BmpView/BmpView.vcxproj [new file with mode: 0644]
include/WTL/Samples/BmpView/BmpView.vcxproj.filters [new file with mode: 0644]
include/WTL/Samples/BmpView/BmpView.vcxproj.user [new file with mode: 0644]
include/WTL/Samples/BmpView/list.h [new file with mode: 0644]
include/WTL/Samples/BmpView/mainfrm.h [new file with mode: 0644]
include/WTL/Samples/BmpView/props.h [new file with mode: 0644]
include/WTL/Samples/BmpView/res/BmpView.ico [new file with mode: 0644]
include/WTL/Samples/BmpView/res/Toolbar.bmp [new file with mode: 0644]
include/WTL/Samples/BmpView/res/ToolbarCE.bmp [new file with mode: 0644]
include/WTL/Samples/BmpView/resource.h [new file with mode: 0644]
include/WTL/Samples/BmpView/resourcece.h [new file with mode: 0644]
include/WTL/Samples/BmpView/resourceppc.h [new file with mode: 0644]
include/WTL/Samples/BmpView/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/BmpView/stdafx.h [new file with mode: 0644]
include/WTL/Samples/BmpView/view.h [new file with mode: 0644]
include/WTL/Samples/GuidGen/GuidGen.cpp [new file with mode: 0644]
include/WTL/Samples/GuidGen/GuidGen.sln [new file with mode: 0644]
include/WTL/Samples/GuidGen/GuidGen.suo [new file with mode: 0644]
include/WTL/Samples/GuidGen/GuidGen.vcxproj [new file with mode: 0644]
include/WTL/Samples/GuidGen/GuidGen.vcxproj.filters [new file with mode: 0644]
include/WTL/Samples/GuidGen/GuidGen.vcxproj.user [new file with mode: 0644]
include/WTL/Samples/GuidGen/aboutdlg.h [new file with mode: 0644]
include/WTL/Samples/GuidGen/maindlg.h [new file with mode: 0644]
include/WTL/Samples/GuidGen/res/GuidGen.ico [new file with mode: 0644]
include/WTL/Samples/GuidGen/resource.h [new file with mode: 0644]
include/WTL/Samples/GuidGen/resourcece.h [new file with mode: 0644]
include/WTL/Samples/GuidGen/stdatl.cpp [new file with mode: 0644]
include/WTL/Samples/GuidGen/stdatl.h [new file with mode: 0644]
include/WTL/Samples/ImageView/ImageView.cpp [new file with mode: 0644]
include/WTL/Samples/ImageView/ImageView.sln [new file with mode: 0644]
include/WTL/Samples/ImageView/ImageView.suo [new file with mode: 0644]
include/WTL/Samples/ImageView/ImageView.vcxproj [new file with mode: 0644]
include/WTL/Samples/ImageView/ImageView.vcxproj.user [new file with mode: 0644]
include/WTL/Samples/ImageView/ImageViewdlg.h [new file with mode: 0644]
include/WTL/Samples/ImageView/ImageViewview.h [new file with mode: 0644]
include/WTL/Samples/ImageView/mainfrm.h [new file with mode: 0644]
include/WTL/Samples/ImageView/res/BmpView.ico [new file with mode: 0644]
include/WTL/Samples/ImageView/res/bitmap1.bmp [new file with mode: 0644]
include/WTL/Samples/ImageView/res/bitmap2.bmp [new file with mode: 0644]
include/WTL/Samples/ImageView/resource.h [new file with mode: 0644]
include/WTL/Samples/ImageView/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/ImageView/stdafx.h [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/HELLO.ICO [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/MDI.ICO [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/MDI.cpp [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/MDI.sln [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/mainfrm.h [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/res/HelloDoc.ico [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/res/MDI.ICO [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/res/Toolbar.bmp [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/res/idr_boun.ico [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/resource.h [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/MDIDocVw/stdafx.h [new file with mode: 0644]
include/WTL/Samples/MTPad/MTPad.cpp [new file with mode: 0644]
include/WTL/Samples/MTPad/MTPad.h [new file with mode: 0644]
include/WTL/Samples/MTPad/MTPad.sln [new file with mode: 0644]
include/WTL/Samples/MTPad/aboutdlg.h [new file with mode: 0644]
include/WTL/Samples/MTPad/finddlg.h [new file with mode: 0644]
include/WTL/Samples/MTPad/mainfrm.h [new file with mode: 0644]
include/WTL/Samples/MTPad/res/MTPad.ico [new file with mode: 0644]
include/WTL/Samples/MTPad/res/MTPadDoc.ico [new file with mode: 0644]
include/WTL/Samples/MTPad/res/Toolbar.bmp [new file with mode: 0644]
include/WTL/Samples/MTPad/res/ToolbarCE.bmp [new file with mode: 0644]
include/WTL/Samples/MTPad/res/printpre.bmp [new file with mode: 0644]
include/WTL/Samples/MTPad/resource.h [new file with mode: 0644]
include/WTL/Samples/MTPad/resourcece.h [new file with mode: 0644]
include/WTL/Samples/MTPad/stdatl.cpp [new file with mode: 0644]
include/WTL/Samples/MTPad/stdatl.h [new file with mode: 0644]
include/WTL/Samples/MTPad/view.h [new file with mode: 0644]
include/WTL/Samples/MiniPie/MiniPie.cpp [new file with mode: 0644]
include/WTL/Samples/MiniPie/MiniPie.sln [new file with mode: 0644]
include/WTL/Samples/MiniPie/MiniPie.suo [new file with mode: 0644]
include/WTL/Samples/MiniPie/MiniPie.vcxproj [new file with mode: 0644]
include/WTL/Samples/MiniPie/MiniPie.vcxproj.user [new file with mode: 0644]
include/WTL/Samples/MiniPie/MiniPieFrame.cpp [new file with mode: 0644]
include/WTL/Samples/MiniPie/MiniPieFrame.h [new file with mode: 0644]
include/WTL/Samples/MiniPie/UrlDlg.cpp [new file with mode: 0644]
include/WTL/Samples/MiniPie/UrlDlg.h [new file with mode: 0644]
include/WTL/Samples/MiniPie/res/MiniPie.ico [new file with mode: 0644]
include/WTL/Samples/MiniPie/resourceppc.h [new file with mode: 0644]
include/WTL/Samples/MiniPie/resourcesp.h [new file with mode: 0644]
include/WTL/Samples/MiniPie/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/MiniPie/stdafx.h [new file with mode: 0644]
include/WTL/Samples/SPControls/SPcontrols.cpp [new file with mode: 0644]
include/WTL/Samples/SPControls/SPcontrols.sln [new file with mode: 0644]
include/WTL/Samples/SPControls/maindlg.h [new file with mode: 0644]
include/WTL/Samples/SPControls/res/SPcontrols.ico [new file with mode: 0644]
include/WTL/Samples/SPControls/resource.h [new file with mode: 0644]
include/WTL/Samples/SPControls/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/SPControls/stdafx.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/AboutDlg.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/AddressCombo.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/BrowserView.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/CustomTabView.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/MainFrm.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/OpenDlg.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/TabBrowser.cpp [new file with mode: 0644]
include/WTL/Samples/TabBrowser/TabBrowser.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/TabBrowser70.sln [new file with mode: 0644]
include/WTL/Samples/TabBrowser/TabBrowser71.sln [new file with mode: 0644]
include/WTL/Samples/TabBrowser/TabBrowser80.sln [new file with mode: 0644]
include/WTL/Samples/TabBrowser/TabBrowser80x.sln [new file with mode: 0644]
include/WTL/Samples/TabBrowser/WindowsDlg.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/res/Go.bmp [new file with mode: 0644]
include/WTL/Samples/TabBrowser/res/PageImage.bmp [new file with mode: 0644]
include/WTL/Samples/TabBrowser/res/TabBrowser.ico [new file with mode: 0644]
include/WTL/Samples/TabBrowser/res/TabToolbar.bmp [new file with mode: 0644]
include/WTL/Samples/TabBrowser/res/Toolbar.bmp [new file with mode: 0644]
include/WTL/Samples/TabBrowser/res/Toolbar_Big.bmp [new file with mode: 0644]
include/WTL/Samples/TabBrowser/resource.h [new file with mode: 0644]
include/WTL/Samples/TabBrowser/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/TabBrowser/stdafx.h [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/ExplorerCombo.H [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/MainFrm.Cpp [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/ShellMgr.Cpp [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/ShellMgr.H [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/WTLExplorer.cpp [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/mainfrm.h [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/res/Toolbar.bmp [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/res/WTLExplorer.ico [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/res/go.bmp [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/res/idt_go1.bmp [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/resource.h [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/WTLExplorer/stdafx.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/FolderDialogStatusText.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizard.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizard.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardCompletionPage.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardCompletionPage.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardFilePreviewPage.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardFilePreviewPage.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardInfo.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardInfo.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardOutputPage.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardOutputPage.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardPathFilterPage.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardPathFilterPage.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardSheet.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardSheet.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardWelcomePage.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard/TestWizardWelcomePage.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard97Test.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard97Test.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/Wizard97Test.sln [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/help/Context.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/help/readme-help.txt [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/res/Wizard97Test.ico [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/res/header.bmp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/res/watermark.bmp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/resource.h [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/stdafx.cpp [new file with mode: 0644]
include/WTL/Samples/Wizard97Test/stdafx.h [new file with mode: 0644]
include/WTL/readme.htm [new file with mode: 0644]
nlite.suo
nlite/nlite.vcxproj
nlite/nlite_nlib.cpp
nlite/nlite_nlib.h

diff --git a/include/WTL/AppWiz/Files/Templates/1033/AboutDlg.cpp b/include/WTL/AppWiz/Files/Templates/1033/AboutDlg.cpp
new file mode 100644 (file)
index 0000000..c1f285a
--- /dev/null
@@ -0,0 +1,20 @@
+// aboutdlg.cpp : implementation of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "aboutdlg.h"
+
+LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CenterWindow(GetParent());
+       return TRUE;
+}
+
+LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       EndDialog(wID);
+       return 0;
+}
diff --git a/include/WTL/AppWiz/Files/Templates/1033/AboutDlg.h b/include/WTL/AppWiz/Files/Templates/1033/AboutDlg.h
new file mode 100644 (file)
index 0000000..cca6b55
--- /dev/null
@@ -0,0 +1,42 @@
+// aboutdlg.h : interface of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CAboutDlg : public CDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTBOX };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+[!endif]
+};
diff --git a/include/WTL/AppWiz/Files/Templates/1033/ChildFrm.cpp b/include/WTL/AppWiz/Files/Templates/1033/ChildFrm.cpp
new file mode 100644 (file)
index 0000000..1f1bac5
--- /dev/null
@@ -0,0 +1,56 @@
+// [!output WTL_CHILD_FRAME_FILE].cpp : implementation of the [!output WTL_CHILD_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+[!if WTL_USE_VIEW]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+#include "[!output WTL_CHILD_FRAME_FILE].h"
+
+void [!output WTL_CHILD_FRAME_CLASS]::OnFinalMessage(HWND /*hWnd*/)
+{
+       delete this;
+}
+
+[!if WTL_USE_VIEW]
+LRESULT [!output WTL_CHILD_FRAME_CLASS]::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+[!if WTL_VIEWTYPE_FORM]
+       m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+       //TODO: Replace with a URL of your choice
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+       m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+       // replace with appropriate values for the app
+       m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+[!endif]
+
+       bHandled = FALSE;
+       return 1;
+}
+
+[!endif]
+LRESULT [!output WTL_CHILD_FRAME_CLASS]::OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+{
+       LPMSG pMsg = (LPMSG)lParam;
+
+[!if WTL_USE_VIEW]
+       if([!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+               return TRUE;
+
+       return m_view.PreTranslateMessage(pMsg);
+[!else]
+       return [!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+}
diff --git a/include/WTL/AppWiz/Files/Templates/1033/ChildFrm.h b/include/WTL/AppWiz/Files/Templates/1033/ChildFrm.h
new file mode 100644 (file)
index 0000000..dd1d742
--- /dev/null
@@ -0,0 +1,85 @@
+// [!output WTL_CHILD_FRAME_FILE].h : interface of the [!output WTL_CHILD_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class [!output WTL_CHILD_FRAME_CLASS] : public [!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MDICHILD)
+
+[!if WTL_USE_VIEW]
+       [!output WTL_VIEW_CLASS] m_view;
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual void OnFinalMessage(HWND /*hWnd*/);
+[!else]
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+[!endif]
+
+       BEGIN_MSG_MAP([!output WTL_CHILD_FRAME_CLASS])
+[!if WTL_USE_VIEW]
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+[!endif]
+               MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg)
+               CHAIN_MSG_MAP([!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_VIEW]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
+[!else]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+[!if WTL_VIEWTYPE_FORM]
+               m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+               //TODO: Replace with a URL of your choice
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+               m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               // replace with appropriate values for the app
+               m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+[!endif]
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LPMSG pMsg = (LPMSG)lParam;
+
+[!if WTL_USE_VIEW]
+               if([!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+[!else]
+               return [!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+       }
+[!endif]
+};
diff --git a/include/WTL/AppWiz/Files/Templates/1033/Frame.cpp b/include/WTL/AppWiz/Files/Templates/1033/Frame.cpp
new file mode 100644 (file)
index 0000000..a2efa64
--- /dev/null
@@ -0,0 +1,391 @@
+// [!output WTL_FRAME_FILE].cpp : implmentation of the [!output WTL_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "aboutdlg.h"
+[!if WTL_USE_VIEW]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+[!if WTL_APPTYPE_MDI]
+#include "[!output WTL_CHILD_FRAME_FILE].h"
+[!endif]
+#include "[!output WTL_FRAME_FILE].h"
+
+BOOL [!output WTL_FRAME_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_APPTYPE_MDI]
+       if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+               return TRUE;
+
+       HWND hWnd = MDIGetActive();
+       if(hWnd != NULL)
+               return (BOOL)::SendMessage(hWnd, WM_FORWARDMSG, 0, (LPARAM)pMsg);
+
+       return FALSE;
+[!else]
+[!if WTL_USE_VIEW]
+       if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+               return TRUE;
+
+       return m_view.PreTranslateMessage(pMsg);
+[!else]
+       return [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+[!endif]
+}
+
+BOOL [!output WTL_FRAME_CLASS]::OnIdle()
+{
+[!if WTL_USE_TOOLBAR]
+       UIUpdateToolBar();
+[!endif]
+       return FALSE;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_REBAR]
+[!if WTL_USE_CMDBAR]
+       // create command bar window
+       HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+       // attach menu
+       m_CmdBar.AttachMenu(GetMenu());
+       // load command bar images
+       m_CmdBar.LoadImages(IDR_MAINFRAME);
+       // remove old menu
+       SetMenu(NULL);
+
+[!endif]
+       HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+       CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+[!if WTL_USE_CMDBAR]
+       AddSimpleReBarBand(hWndCmdBar);
+       AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+[!else]
+       AddSimpleReBarBand(hWndToolBar);
+[!endif]
+[!else]
+       CreateSimpleToolBar();
+[!endif]
+[!endif]
+[!if WTL_USE_STATUSBAR]
+
+       CreateSimpleStatusBar();
+[!endif]
+[!if WTL_APPTYPE_MDI]
+
+       CreateMDIClient();
+[!if WTL_USE_CMDBAR]
+       m_CmdBar.SetMDIClient(m_hWndMDIClient);
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+
+       m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+       //TODO: Replace with a URL of your choice
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+       m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+       // replace with appropriate values for the app
+       m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+
+       m_hWndClient = m_splitter.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+
+       m_pane.SetPaneContainerExtendedStyle(PANECNT_NOBORDER);
+       m_pane.Create(m_splitter, _T("Tree"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+       m_treeview.Create(m_pane, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE);
+       m_treeview.SetFont(AtlGetDefaultGuiFont());
+       m_pane.SetClient(m_treeview);
+[!if WTL_VIEWTYPE_FORM]
+
+       m_view.Create(m_splitter);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+       //TODO: Replace with a URL of your choice
+       m_view.Create(m_splitter, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+
+       m_view.Create(m_splitter, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+       m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+       // replace with appropriate values for the app
+       m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+
+       m_splitter.SetSplitterPanes(m_pane, m_view);
+       UpdateLayout();
+       m_splitter.SetSplitterPosPct(25);
+[!endif]
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_REBAR]
+
+       UIAddToolBar(hWndToolBar);
+[!else]
+
+       UIAddToolBar(m_hWndToolBar);
+[!endif]
+       UISetCheck(ID_VIEW_TOOLBAR, 1);
+[!endif]
+[!if WTL_USE_STATUSBAR]
+       UISetCheck(ID_VIEW_STATUS_BAR, 1);
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+       UISetCheck(ID_VIEW_TREEPANE, 1);
+[!endif]
+
+       // register object for message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->AddMessageFilter(this);
+       pLoop->AddIdleHandler(this);
+
+[!if WTL_APPTYPE_TABVIEW]
+[!if WTL_USE_CMDBAR]
+       CMenuHandle menuMain = m_CmdBar.GetMenu();
+[!else]
+       CMenuHandle menuMain = GetMenu();
+[!endif]
+       m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));
+
+[!endif]
+       return 0;
+}
+
+[!if WTL_COM_SERVER]
+LRESULT [!output WTL_FRAME_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.AttachMenu(NULL);
+
+[!endif]
+[!endif]
+       // unregister message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->RemoveMessageFilter(this);
+       pLoop->RemoveIdleHandler(this);
+
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+
+[!if WTL_APPTYPE_MTSDI]
+       ::PostQuitMessage(1);
+
+[!endif]
+       return 0;
+}
+
+[!else]
+LRESULT [!output WTL_FRAME_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.AttachMenu(NULL);
+
+[!endif]
+[!endif]
+       // unregister message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->RemoveMessageFilter(this);
+       pLoop->RemoveIdleHandler(this);
+
+       bHandled = FALSE;
+       return 1;
+}
+
+[!endif]
+LRESULT [!output WTL_FRAME_CLASS]::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       PostMessage(WM_CLOSE);
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+[!if WTL_APPTYPE_TABVIEW]
+       [!output WTL_VIEW_CLASS]* pView = new [!output WTL_VIEW_CLASS];
+[!if WTL_VIEWTYPE_FORM]
+       pView->Create(m_view);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+       //TODO: Replace with a URL of your choice
+       pView->Create(m_view, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+       pView->Create(m_view, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+       pView->SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+       // replace with appropriate values for the app
+       pView->SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+       m_view.AddPage(pView->m_hWnd, _T("Document"));
+
+[!endif]
+[!if WTL_APPTYPE_MDI]
+       [!output WTL_CHILD_FRAME_CLASS]* pChild = new [!output WTL_CHILD_FRAME_CLASS];
+       pChild->CreateEx(m_hWndClient);
+
+[!endif]
+       // TODO: add code to initialize document
+
+       return 0;
+}
+
+[!if WTL_APPTYPE_MTSDI]
+LRESULT [!output WTL_FRAME_CLASS]::OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
+       return 0;
+}
+
+[!endif]
+[!if WTL_USE_TOOLBAR]
+LRESULT [!output WTL_FRAME_CLASS]::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+[!if WTL_USE_REBAR]
+       static BOOL bVisible = TRUE;    // initially visible
+       bVisible = !bVisible;
+       CReBarCtrl rebar = m_hWndToolBar;
+[!if WTL_USE_CMDBAR]
+       int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);       // toolbar is 2nd added band
+[!else]
+       int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST);   // toolbar is first 1st band
+[!endif]
+       rebar.ShowBand(nBandIndex, bVisible);
+[!else]
+       BOOL bVisible = !::IsWindowVisible(m_hWndToolBar);
+       ::ShowWindow(m_hWndToolBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+[!endif]
+       UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+       UpdateLayout();
+       return 0;
+}
+
+[!endif]
+[!if WTL_USE_STATUSBAR]
+LRESULT [!output WTL_FRAME_CLASS]::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+       ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+       UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+       UpdateLayout();
+       return 0;
+}
+
+[!endif]
+LRESULT [!output WTL_FRAME_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CAboutDlg dlg;
+       dlg.DoModal();
+       return 0;
+}
+[!if WTL_APPTYPE_MDI]
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowCascade(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       MDICascade();
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowTile(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       MDITile();
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowArrangeIcons(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       MDIIconArrange();
+       return 0;
+}
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       int nActivePage = m_view.GetActivePage();
+       if(nActivePage != -1)
+               m_view.RemovePage(nActivePage);
+       else
+               ::MessageBeep((UINT)-1);
+
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       m_view.RemoveAllPages();
+
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       int nPage = wID - ID_WINDOW_TABFIRST;
+       m_view.SetActivePage(nPage);
+
+       return 0;
+}
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+
+LRESULT [!output WTL_FRAME_CLASS]::OnViewTreePane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       bool bShow = (m_splitter.GetSinglePaneMode() != SPLIT_PANE_NONE);
+       m_splitter.SetSinglePaneMode(bShow ? SPLIT_PANE_NONE : SPLIT_PANE_RIGHT);
+       UISetCheck(ID_VIEW_TREEPANE, bShow);
+
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnTreePaneClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND hWndCtl, BOOL& /*bHandled*/)
+{
+       if(hWndCtl == m_pane.m_hWnd)
+       {
+               m_splitter.SetSinglePaneMode(SPLIT_PANE_RIGHT);
+               UISetCheck(ID_VIEW_TREEPANE, 0);
+       }
+
+       return 0;
+}
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1033/Frame.h b/include/WTL/AppWiz/Files/Templates/1033/Frame.h
new file mode 100644 (file)
index 0000000..7fba4fc
--- /dev/null
@@ -0,0 +1,543 @@
+// [!output WTL_FRAME_FILE].h : interface of the [!output WTL_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_APPTYPE_TABVIEW]
+#define WINDOW_MENU_POSITION   3
+
+[!endif]
+class [!output WTL_FRAME_CLASS] : public [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>, public CUpdateUI<[!output WTL_FRAME_CLASS]>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
+
+[!if WTL_APPTYPE_TABVIEW]
+       CTabView m_view;
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+       CSplitterWindow m_splitter;
+       CPaneContainer m_pane;
+       CTreeViewCtrl m_treeview;
+       [!output WTL_VIEW_CLASS] m_view;
+[!endif]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+       [!output WTL_VIEW_CLASS] m_view;
+
+[!endif]
+[!endif]
+[!if WTL_USE_CMDBAR]
+[!if WTL_APPTYPE_MDI]
+       CMDICommandBarCtrl m_CmdBar;
+
+[!else]
+       CCommandBarCtrl m_CmdBar;
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_APPTYPE_MDI]
+               if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               HWND hWnd = MDIGetActive();
+               if(hWnd != NULL)
+                       return (BOOL)::SendMessage(hWnd, WM_FORWARDMSG, 0, (LPARAM)pMsg);
+
+               return FALSE;
+[!else]
+[!if WTL_USE_VIEW]
+               if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+[!else]
+               return [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+[!endif]
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL OnIdle();
+[!else]
+       virtual BOOL OnIdle()
+       {
+[!if WTL_USE_TOOLBAR]
+               UIUpdateToolBar();
+[!endif]
+               return FALSE;
+       }
+[!endif]
+
+       BEGIN_UPDATE_UI_MAP([!output WTL_FRAME_CLASS])
+[!if WTL_USE_TOOLBAR]
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+               UPDATE_ELEMENT(ID_VIEW_TREEPANE, UPDUI_MENUPOPUP)
+[!endif]
+       END_UPDATE_UI_MAP()
+
+       BEGIN_MSG_MAP([!output WTL_FRAME_CLASS])
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+[!if WTL_APPTYPE_MTSDI]
+               COMMAND_ID_HANDLER(ID_FILE_NEW_WINDOW, OnFileNewWindow)
+[!endif]
+[!if WTL_USE_TOOLBAR]
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+[!if WTL_APPTYPE_MDI]
+               COMMAND_ID_HANDLER(ID_WINDOW_CASCADE, OnWindowCascade)
+               COMMAND_ID_HANDLER(ID_WINDOW_TILE_HORZ, OnWindowTile)
+               COMMAND_ID_HANDLER(ID_WINDOW_ARRANGE, OnWindowArrangeIcons)
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+               COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose)
+               COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll)
+               COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+               COMMAND_ID_HANDLER(ID_VIEW_TREEPANE, OnViewTreePane)
+               COMMAND_ID_HANDLER(ID_PANE_CLOSE, OnTreePaneClose)
+[!endif]
+               CHAIN_MSG_MAP(CUpdateUI<[!output WTL_FRAME_CLASS]>)
+               CHAIN_MSG_MAP([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_REBAR]
+[!if WTL_USE_CMDBAR]
+               // create command bar window
+               HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+               // attach menu
+               m_CmdBar.AttachMenu(GetMenu());
+               // load command bar images
+               m_CmdBar.LoadImages(IDR_MAINFRAME);
+               // remove old menu
+               SetMenu(NULL);
+
+[!endif]
+               HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+               CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+[!if WTL_USE_CMDBAR]
+               AddSimpleReBarBand(hWndCmdBar);
+               AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+[!else]
+               AddSimpleReBarBand(hWndToolBar);
+[!endif]
+[!else]
+               CreateSimpleToolBar();
+[!endif]
+[!endif]
+[!if WTL_USE_STATUSBAR]
+
+               CreateSimpleStatusBar();
+[!endif]
+[!if WTL_APPTYPE_MDI]
+
+               CreateMDIClient();
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.SetMDIClient(m_hWndMDIClient);
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+
+               m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+               //TODO: Replace with a URL of your choice
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+               m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               // replace with appropriate values for the app
+               m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+
+               m_hWndClient = m_splitter.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+
+               m_pane.SetPaneContainerExtendedStyle(PANECNT_NOBORDER);
+               m_pane.Create(m_splitter, _T("Tree"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+               m_treeview.Create(m_pane, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE);
+               m_treeview.SetFont(AtlGetDefaultGuiFont());
+               m_pane.SetClient(m_treeview);
+[!if WTL_VIEWTYPE_FORM]
+
+               m_view.Create(m_splitter);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+               //TODO: Replace with a URL of your choice
+               m_view.Create(m_splitter, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+
+               m_view.Create(m_splitter, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+               m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               // replace with appropriate values for the app
+               m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+
+               m_splitter.SetSplitterPanes(m_pane, m_view);
+               UpdateLayout();
+               m_splitter.SetSplitterPosPct(25);
+[!endif]
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_REBAR]
+
+               UIAddToolBar(hWndToolBar);
+[!else]
+
+               UIAddToolBar(m_hWndToolBar);
+[!endif]
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+               UISetCheck(ID_VIEW_TREEPANE, 1);
+[!endif]
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+[!if WTL_APPTYPE_TABVIEW]
+[!if WTL_USE_CMDBAR]
+               CMenuHandle menuMain = m_CmdBar.GetMenu();
+[!else]
+               CMenuHandle menuMain = GetMenu();
+[!endif]
+               m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));
+
+[!endif]
+               return 0;
+       }
+[!endif]
+[!if WTL_COM_SERVER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.AttachMenu(NULL);
+
+[!endif]
+[!endif]
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+
+[!if WTL_APPTYPE_MTSDI]
+               ::PostQuitMessage(1);
+
+[!endif]
+               return 0;
+       }
+[!endif]
+[!else]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
+[!else]
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.AttachMenu(NULL);
+
+[!endif]
+[!endif]
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+
+               bHandled = FALSE;
+               return 1;
+       }
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_APPTYPE_TABVIEW]
+               [!output WTL_VIEW_CLASS]* pView = new [!output WTL_VIEW_CLASS];
+[!if WTL_VIEWTYPE_FORM]
+               pView->Create(m_view);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+               //TODO: Replace with a URL of your choice
+               pView->Create(m_view, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+               pView->Create(m_view, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+               pView->SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               // replace with appropriate values for the app
+               pView->SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+               m_view.AddPage(pView->m_hWnd, _T("Document"));
+
+[!endif]
+[!if WTL_APPTYPE_MDI]
+               [!output WTL_CHILD_FRAME_CLASS]* pChild = new [!output WTL_CHILD_FRAME_CLASS];
+               pChild->CreateEx(m_hWndClient);
+
+[!endif]
+               // TODO: add code to initialize document
+
+               return 0;
+       }
+[!endif]
+[!if WTL_APPTYPE_MTSDI]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
+               return 0;
+       }
+[!endif]
+[!endif]
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_USE_REBAR]
+               static BOOL bVisible = TRUE;    // initially visible
+               bVisible = !bVisible;
+               CReBarCtrl rebar = m_hWndToolBar;
+[!if WTL_USE_CMDBAR]
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);       // toolbar is 2nd added band
+[!else]
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST);   // toolbar is first 1st band
+[!endif]
+               rebar.ShowBand(nBandIndex, bVisible);
+[!else]
+               BOOL bVisible = !::IsWindowVisible(m_hWndToolBar);
+               ::ShowWindow(m_hWndToolBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+[!endif]
+               UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+[!endif]
+[!endif]
+[!if WTL_USE_STATUSBAR]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+[!endif]
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowCascade(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowCascade(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               MDICascade();
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowTile(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowTile(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               MDITile();
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowArrangeIcons(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowArrangeIcons(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               MDIIconArrange();
+               return 0;
+       }
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               int nActivePage = m_view.GetActivePage();
+               if(nActivePage != -1)
+                       m_view.RemovePage(nActivePage);
+               else
+                       ::MessageBeep((UINT)-1);
+
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               m_view.RemoveAllPages();
+
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       int nPage = wID - ID_WINDOW_TABFIRST;
+       m_view.SetActivePage(nPage);
+
+       return 0;
+}
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnViewTreePane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnViewTreePane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               bool bShow = (m_splitter.GetSinglePaneMode() != SPLIT_PANE_NONE);
+               m_splitter.SetSinglePaneMode(bShow ? SPLIT_PANE_NONE : SPLIT_PANE_RIGHT);
+               UISetCheck(ID_VIEW_TREEPANE, bShow);
+
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnTreePaneClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND hWndCtl, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnTreePaneClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND hWndCtl, BOOL& /*bHandled*/)
+       {
+               if(hWndCtl == m_pane.m_hWnd)
+               {
+                       m_splitter.SetSinglePaneMode(SPLIT_PANE_RIGHT);
+                       UISetCheck(ID_VIEW_TREEPANE, 0);
+               }
+
+               return 0;
+       }
+[!endif]
+[!endif]
+};
diff --git a/include/WTL/AppWiz/Files/Templates/1033/MainDlg.cpp b/include/WTL/AppWiz/Files/Templates/1033/MainDlg.cpp
new file mode 100644 (file)
index 0000000..5e16279
--- /dev/null
@@ -0,0 +1,167 @@
+// [!output WTL_MAINDLG_FILE].cpp : implementation of the [!output WTL_MAINDLG_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+#include "aboutdlg.h"
+[!endif]
+#include "[!output WTL_MAINDLG_FILE].h"
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+BOOL [!output WTL_MAINDLG_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_HOST_AX]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       HWND hWndCtl = ::GetFocus();
+       if(IsChild(hWndCtl))
+       {
+               // find a direct child of the dialog from the window that has focus
+               while(::GetParent(hWndCtl) != m_hWnd)
+                       hWndCtl = ::GetParent(hWndCtl);
+
+               // give control a chance to translate this message
+               if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                       return TRUE;
+       }
+
+[!endif]
+       return CWindow::IsDialogMessage(pMsg);
+}
+
+BOOL [!output WTL_MAINDLG_CLASS]::OnIdle()
+{
+       return FALSE;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // center the dialog on the screen
+       CenterWindow();
+
+       // set icons
+       HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+       SetIcon(hIcon, TRUE);
+       HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+       SetIcon(hIconSmall, FALSE);
+
+       // register object for message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->AddMessageFilter(this);
+       pLoop->AddIdleHandler(this);
+
+       UIAddChildWindowContainer(m_hWnd);
+
+       return TRUE;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // unregister message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->RemoveMessageFilter(this);
+       pLoop->RemoveIdleHandler(this);
+[!if WTL_COM_SERVER]
+
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+[!endif]
+
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CAboutDlg dlg;
+       dlg.DoModal();
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: Add validation code 
+       CloseDialog(wID);
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CloseDialog(wID);
+       return 0;
+}
+
+void [!output WTL_MAINDLG_CLASS]::CloseDialog(int nVal)
+{
+       DestroyWindow();
+       ::PostQuitMessage(nVal);
+}
+[!endif]
+[!if WTL_APPTYPE_DLG && WTL_APPTYPE_DLG_MODAL]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+
+[!endif]
+       // center the dialog on the screen
+       CenterWindow();
+
+       // set icons
+       HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+       SetIcon(hIcon, TRUE);
+       HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+       SetIcon(hIconSmall, FALSE);
+
+       return TRUE;
+}
+
+[!if WTL_COM_SERVER]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+       return 0;
+}
+
+[!endif]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CSimpleDialog<IDD_ABOUTBOX, FALSE> dlg;
+       dlg.DoModal();
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: Add validation code 
+       EndDialog(wID);
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       EndDialog(wID);
+       return 0;
+}
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1033/MainDlg.h b/include/WTL/AppWiz/Files/Templates/1033/MainDlg.h
new file mode 100644 (file)
index 0000000..54e6f41
--- /dev/null
@@ -0,0 +1,259 @@
+// [!output WTL_MAINDLG_FILE].h : interface of the [!output WTL_MAINDLG_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+class [!output WTL_MAINDLG_CLASS] : public [!output WTL_MAINDLG_BASE_CLASS]<[!output WTL_MAINDLG_CLASS]>, public CUpdateUI<[!output WTL_MAINDLG_CLASS]>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       enum { IDD = IDD_MAINDLG };
+
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_HOST_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+[!endif]
+               return CWindow::IsDialogMessage(pMsg);
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL OnIdle();
+[!else]
+       virtual BOOL OnIdle()
+       {
+               return FALSE;
+       }
+[!endif]
+
+       BEGIN_UPDATE_UI_MAP([!output WTL_MAINDLG_CLASS])
+       END_UPDATE_UI_MAP()
+
+       BEGIN_MSG_MAP([!output WTL_MAINDLG_CLASS])
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_ID_HANDLER(IDOK, OnOK)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // center the dialog on the screen
+               CenterWindow();
+
+               // set icons
+               HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+               SetIcon(hIcon, TRUE);
+               HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+               SetIcon(hIconSmall, FALSE);
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               UIAddChildWindowContainer(m_hWnd);
+
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+[!if WTL_COM_SERVER]
+
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+[!endif]
+
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: Add validation code 
+               CloseDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CloseDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+       void CloseDialog(int nVal);
+[!else]
+       void CloseDialog(int nVal)
+       {
+               DestroyWindow();
+               ::PostQuitMessage(nVal);
+       }
+[!endif]
+};
+[!endif]
+[!if WTL_APPTYPE_DLG && WTL_APPTYPE_DLG_MODAL]
+class [!output WTL_MAINDLG_CLASS] : public [!output WTL_MAINDLG_BASE_CLASS]<[!output WTL_MAINDLG_CLASS]>
+{
+public:
+       enum { IDD = IDD_MAINDLG };
+
+       BEGIN_MSG_MAP([!output WTL_MAINDLG_CLASS])
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+[!if WTL_COM_SERVER]
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_ID_HANDLER(IDOK, OnOK)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_COM_SERVER]
+               _Module.Lock();
+
+[!endif]
+               // center the dialog on the screen
+               CenterWindow();
+
+               // set icons
+               HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+               SetIcon(hIcon, TRUE);
+               HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+               SetIcon(hIconSmall, FALSE);
+
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_COM_SERVER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CSimpleDialog<IDD_ABOUTBOX, FALSE> dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: Add validation code 
+               EndDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+[!endif]
+};
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1033/View.cpp b/include/WTL/AppWiz/Files/Templates/1033/View.cpp
new file mode 100644 (file)
index 0000000..9798d3e
--- /dev/null
@@ -0,0 +1,63 @@
+// [!output WTL_VIEW_FILE].cpp : implementation of the [!output WTL_VIEW_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "[!output WTL_VIEW_FILE].h"
+
+BOOL [!output WTL_VIEW_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_HOST_AX]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       HWND hWndCtl = ::GetFocus();
+       if(IsChild(hWndCtl))
+       {
+               // find a direct child of the dialog from the window that has focus
+               while(::GetParent(hWndCtl) != m_hWnd)
+                       hWndCtl = ::GetParent(hWndCtl);
+
+               // give control a chance to translate this message
+               if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                       return TRUE;
+       }
+
+[!endif]
+[!if WTL_VIEWTYPE_HTML]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       // give HTML page a chance to translate this message
+       return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+       return CWindow::IsDialogMessage(pMsg);
+[!else]
+       pMsg;
+       return FALSE;
+[!endif]
+[!endif]
+}
+[!if WTL_VIEWTYPE_SCROLL]
+
+void [!output WTL_VIEW_CLASS]::DoPaint(CDCHandle dc)
+{
+       //TODO: Add your drawing code here
+}
+[!endif]
+[!if WTL_VIEWTYPE_GENERIC]
+
+LRESULT [!output WTL_VIEW_CLASS]::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CPaintDC dc(m_hWnd);
+
+       //TODO: Add your drawing code here
+
+       return 0;
+}
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1033/View.h b/include/WTL/AppWiz/Files/Templates/1033/View.h
new file mode 100644 (file)
index 0000000..75207d0
--- /dev/null
@@ -0,0 +1,107 @@
+// [!output WTL_VIEW_FILE].h : interface of the [!output WTL_VIEW_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_VIEWTYPE_GENERIC || WTL_VIEWTYPE_FORM || WTL_VIEWTYPE_SCROLL]
+class [!output WTL_VIEW_CLASS] : public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS]>
+[!else]
+class [!output WTL_VIEW_CLASS] : public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS], [!output WTL_VIEW_BASE]>
+[!endif]
+{
+public:
+[!if WTL_VIEWTYPE_GENERIC || WTL_VIEWTYPE_SCROLL]
+       DECLARE_WND_CLASS(NULL)
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+       enum { IDD = IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM };
+[!else]
+       DECLARE_WND_SUPERCLASS(NULL, [!output WTL_VIEW_BASE]::GetWndClassName())
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+       BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_HOST_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+[!endif]
+[!if WTL_VIEWTYPE_HTML]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               // give HTML page a chance to translate this message
+               return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+               return CWindow::IsDialogMessage(pMsg);
+[!else]
+               pMsg;
+               return FALSE;
+[!endif]
+[!endif]
+       }
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+[!if WTL_USE_CPP_FILES]
+
+       void DoPaint(CDCHandle dc);
+[!else]
+
+       void DoPaint(CDCHandle dc)
+       {
+               //TODO: Add your drawing code here
+       }
+[!endif]
+[!endif]
+
+       BEGIN_MSG_MAP([!output WTL_VIEW_CLASS])
+[!if WTL_VIEWTYPE_GENERIC]
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               CHAIN_MSG_MAP([!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS]>)
+[!endif]
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+[!if WTL_VIEWTYPE_GENERIC]
+[!if WTL_USE_CPP_FILES]
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CPaintDC dc(m_hWnd);
+
+               //TODO: Add your drawing code here
+
+               return 0;
+       }
+[!endif]
+[!endif]
+};
diff --git a/include/WTL/AppWiz/Files/Templates/1033/resource.h b/include/WTL/AppWiz/Files/Templates/1033/resource.h
new file mode 100644 (file)
index 0000000..5c2fed9
--- /dev/null
@@ -0,0 +1,59 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by [!output PROJECT_NAME].RC
+//
+
+[!if WTL_COM_SERVER]
+#define IDS_PROJNAME                           100
+#define IDR_[!output UPPERCASE_SAFE_PROJECT_NAME]      100
+[!endif]
+
+#define IDD_ABOUTBOX                           100
+#define IDR_MAINFRAME                          128
+//#define IDR_[!output UPPERCASE_SAFE_PROJECT_NAME]TYPE        129
+[!if WTL_APPTYPE_MDI]
+#define IDR_MDICHILD                           129
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 130
+[!endif]
+[!endif]
+[!else]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_TABVIEW || WTL_APPTYPE_EXPLORER]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 129
+[!endif]
+[!endif]
+[!else]
+[!if WTL_APPTYPE_DLG]
+#define IDD_MAINDLG                            129
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 130
+[!endif]
+[!endif]
+#define ID_FILE_NEW_WINDOW                     32771
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+#define ID_WINDOW_CLOSE                                32772
+#define ID_WINDOW_CLOSE_ALL                    32773
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+#define ID_VIEW_TREEPANE                       32774
+[!endif]
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE       201
+#define _APS_NEXT_CONTROL_VALUE                1000
+#define _APS_NEXT_SYMED_VALUE          101
+#define _APS_NEXT_COMMAND_VALUE                32775
+#endif
+#endif
diff --git a/include/WTL/AppWiz/Files/Templates/1033/root.cpp b/include/WTL/AppWiz/Files/Templates/1033/root.cpp
new file mode 100644 (file)
index 0000000..b82d19f
--- /dev/null
@@ -0,0 +1,376 @@
+// [!output PROJECT_NAME].cpp : main source file for [!output PROJECT_NAME].exe
+//
+
+#include "stdafx.h"
+[!if !WTL_USE_CPP_FILES]
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+[!if WTL_USE_CMDBAR]
+#include <atlctrlw.h>
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+#include <atlctrlx.h>
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+#include <atlctrlx.h>
+#include <atlsplit.h>
+[!endif]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_SCROLL]
+#include <atlscrl.h>
+[!endif]
+[!endif]
+[!endif]
+
+#include "resource.h"
+
+[!if WTL_COM_SERVER]
+// Note: Proxy/Stub Information
+//             To build a separate proxy/stub DLL, 
+//             run nmake -f [!output PROJECT_NAME]ps.mk in the project directory.
+#include "initguid.h"
+#include "[!output PROJECT_NAME].h"
+#include "[!output PROJECT_NAME]_i.c"
+
+[!endif]
+[!if WTL_USE_VIEW]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+[!if !WTL_APPTYPE_DLG_MODAL]
+#include "aboutdlg.h"
+[!endif]
+[!if WTL_APPTYPE_MDI]
+#include "[!output WTL_CHILD_FRAME_FILE].h"
+[!endif]
+[!if WTL_APPTYPE_DLG]
+#include "[!output WTL_MAINDLG_FILE].h"
+[!else]
+#include "[!output WTL_FRAME_FILE].h"
+[!endif]
+[!if WTL_COM_SERVER]
+
+CServerAppModule _Module;
+
+BEGIN_OBJECT_MAP(ObjectMap)
+END_OBJECT_MAP()
+[!else]
+
+CAppModule _Module;
+[!endif]
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       [!output WTL_MAINDLG_CLASS] dlgMain;
+
+       if(dlgMain.Create(NULL) == NULL)
+       {
+               ATLTRACE(_T("Main dialog creation failed!\n"));
+               return 0;
+       }
+
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+[!endif]
+       dlgMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+[!endif]
+[!if !WTL_APPTYPE_DLG && WTL_APPTYPE_MTSDI]
+
+class C[!output SAFE_PROJECT_NAME]ThreadManager
+{
+public:
+       // thread init param
+       struct _RunData
+       {
+               LPTSTR lpstrCmdLine;
+               int nCmdShow;
+       };
+
+       // thread proc
+       static DWORD WINAPI RunThread(LPVOID lpData)
+       {
+               CMessageLoop theLoop;
+               _Module.AddMessageLoop(&theLoop);
+
+               _RunData* pData = (_RunData*)lpData;
+               [!output WTL_FRAME_CLASS] wndFrame;
+
+               if(wndFrame.CreateEx() == NULL)
+               {
+                       ATLTRACE(_T("Frame window creation failed!\n"));
+                       return 0;
+               }
+
+[!if WTL_COM_SERVER]
+               _Module.Lock();
+[!endif]
+               wndFrame.ShowWindow(pData->nCmdShow);
+               ::SetForegroundWindow(wndFrame);        // Win95 needs this
+               delete pData;
+
+               int nRet = theLoop.Run();
+
+               _Module.RemoveMessageLoop();
+               return nRet;
+       }
+
+       DWORD m_dwCount;
+       HANDLE m_arrThreadHandles[MAXIMUM_WAIT_OBJECTS - 1];
+
+       C[!output SAFE_PROJECT_NAME]ThreadManager() : m_dwCount(0)
+       { }
+
+// Operations
+       DWORD AddThread(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               if(m_dwCount == (MAXIMUM_WAIT_OBJECTS - 1))
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create ANY MORE threads!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       return 0;
+               }
+
+               _RunData* pData = new _RunData;
+               pData->lpstrCmdLine = lpstrCmdLine;
+               pData->nCmdShow = nCmdShow;
+               DWORD dwThreadID;
+               HANDLE hThread = ::CreateThread(NULL, 0, RunThread, pData, 0, &dwThreadID);
+               if(hThread == NULL)
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create thread!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       return 0;
+               }
+
+               m_arrThreadHandles[m_dwCount] = hThread;
+               m_dwCount++;
+               return dwThreadID;
+       }
+
+       void RemoveThread(DWORD dwIndex)
+       {
+               ::CloseHandle(m_arrThreadHandles[dwIndex]);
+               if(dwIndex != (m_dwCount - 1))
+                       m_arrThreadHandles[dwIndex] = m_arrThreadHandles[m_dwCount - 1];
+               m_dwCount--;
+       }
+
+       int Run(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               MSG msg;
+               // force message queue to be created
+               ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+
+               AddThread(lpstrCmdLine, nCmdShow);
+
+               int nRet = m_dwCount;
+               DWORD dwRet;
+               while(m_dwCount > 0)
+               {
+                       dwRet = ::MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles, FALSE, INFINITE, QS_ALLINPUT);
+
+                       if(dwRet == 0xFFFFFFFF)
+                       {
+                               ::MessageBox(NULL, _T("ERROR: Wait for multiple objects failed!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       }
+                       else if(dwRet >= WAIT_OBJECT_0 && dwRet <= (WAIT_OBJECT_0 + m_dwCount - 1))
+                       {
+                               RemoveThread(dwRet - WAIT_OBJECT_0);
+                       }
+                       else if(dwRet == (WAIT_OBJECT_0 + m_dwCount))
+                       {
+                               if(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+                               {
+                                       if(msg.message == WM_USER)
+                                               AddThread(_T(""), SW_SHOWNORMAL);
+                               }
+                       }
+                       else
+                       {
+                               ::MessageBeep((UINT)-1);
+                       }
+               }
+
+               return nRet;
+       }
+};
+[!endif]
+[!if !WTL_APPTYPE_DLG && !WTL_APPTYPE_MTSDI]
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       [!output WTL_FRAME_CLASS] wndMain;
+
+       if(wndMain.CreateEx() == NULL)
+       {
+               ATLTRACE(_T("Main window creation failed!\n"));
+               return 0;
+       }
+
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+[!endif]
+       wndMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+[!endif]
+[!if !WTL_APPTYPE_DLG_MODAL]
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+[!else]
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)
+[!endif]
+{
+       HRESULT hRes = ::CoInitialize(NULL);
+// If you are running on NT 4.0 or higher you can use the following call instead to 
+// make the EXE free threaded. This means that calls come in on a random RPC thread.
+//     HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
+       ::DefWindowProc(NULL, 0, 0, 0L);
+
+[!if !WTL_USE_TOOLBAR || !WTL_USE_REBAR]
+       AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls
+[!else]
+       AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);      // add flags to support other controls
+[!endif]
+[!if WTL_COM_SERVER]
+
+       GUID guid;
+       hRes = _Module.Init(ObjectMap, hInstance, &guid);
+       ATLASSERT(SUCCEEDED(hRes));
+
+[!else]
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+[!endif]
+[!if WTL_USE_VIEW && WTL_VIEWTYPE_RICHEDIT]
+       HMODULE hInstRich = ::LoadLibrary(CRichEditCtrl::GetLibraryName());
+       ATLASSERT(hInstRich != NULL);
+
+[!endif]
+[!if WTL_ENABLE_AX]
+       AtlAxWinInit();
+
+[!endif]
+[!if WTL_COM_SERVER]
+       // Parse command line, register or unregister or run the server
+       int nRet = 0;
+       TCHAR szTokens[] = _T("-/");
+       bool bRun = true;
+       bool bAutomation = false;
+
+       LPCTSTR lpszToken = _Module.FindOneOf(::GetCommandLine(), szTokens);
+       while(lpszToken != NULL)
+       {
+               if(lstrcmpi(lpszToken, _T("UnregServer")) == 0)
+               {
+                       _Module.UpdateRegistryFromResource(IDR_[!output UPPERCASE_SAFE_PROJECT_NAME], FALSE);
+                       nRet = _Module.UnregisterServer(TRUE);
+                       bRun = false;
+                       break;
+               }
+               else if(lstrcmpi(lpszToken, _T("RegServer")) == 0)
+               {
+                       _Module.UpdateRegistryFromResource(IDR_[!output UPPERCASE_SAFE_PROJECT_NAME], TRUE);
+                       nRet = _Module.RegisterServer(TRUE);
+                       bRun = false;
+                       break;
+               }
+               else if((lstrcmpi(lpszToken, _T("Automation")) == 0) ||
+                       (lstrcmpi(lpszToken, _T("Embedding")) == 0))
+               {
+                       bAutomation = true;
+                       break;
+               }
+               lpszToken = _Module.FindOneOf(lpszToken, szTokens);
+       }
+
+       if(bRun)
+       {
+               _Module.StartMonitor();
+               hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
+               ATLASSERT(SUCCEEDED(hRes));
+               hRes = ::CoResumeClassObjects();
+               ATLASSERT(SUCCEEDED(hRes));
+
+               if(bAutomation)
+               {
+                       CMessageLoop theLoop;
+                       nRet = theLoop.Run();
+               }
+               else
+[!if WTL_APPTYPE_DLG_MODAL]
+               {
+                       [!output WTL_MAINDLG_CLASS] dlgMain;
+                       nRet = dlgMain.DoModal();
+               }
+[!else]
+[!if WTL_APPTYPE_MTSDI]
+               {
+                       C[!output SAFE_PROJECT_NAME]ThreadManager mgr;
+                       nRet = mgr.Run(lpstrCmdLine, nCmdShow);
+               }
+[!else]
+               {
+                       nRet = Run(lpstrCmdLine, nCmdShow);
+               }
+[!endif]
+[!endif]
+
+               _Module.RevokeClassObjects();
+               ::Sleep(_Module.m_dwPause);
+       }
+[!else]
+[!if WTL_APPTYPE_DLG_MODAL]
+       int nRet = 0;
+       // BLOCK: Run application
+       {
+               [!output WTL_MAINDLG_CLASS] dlgMain;
+               nRet = dlgMain.DoModal();
+       }
+[!else]
+[!if WTL_APPTYPE_MTSDI]
+       int nRet = 0;
+       // BLOCK: Run application
+       {
+               C[!output SAFE_PROJECT_NAME]ThreadManager mgr;
+               nRet = mgr.Run(lpstrCmdLine, nCmdShow);
+       }
+[!else]
+       int nRet = Run(lpstrCmdLine, nCmdShow);
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_RICHEDIT]
+
+       ::FreeLibrary(hInstRich);
+[!endif]
+[!endif]
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/AppWiz/Files/Templates/1033/root.h b/include/WTL/AppWiz/Files/Templates/1033/root.h
new file mode 100644 (file)
index 0000000..0c8afa9
--- /dev/null
@@ -0,0 +1 @@
+// [!output PROJECT_NAME].h
diff --git a/include/WTL/AppWiz/Files/Templates/1033/root.ico b/include/WTL/AppWiz/Files/Templates/1033/root.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/AppWiz/Files/Templates/1033/root.ico differ
diff --git a/include/WTL/AppWiz/Files/Templates/1033/rootDoc.ico b/include/WTL/AppWiz/Files/Templates/1033/rootDoc.ico
new file mode 100644 (file)
index 0000000..af5edfa
Binary files /dev/null and b/include/WTL/AppWiz/Files/Templates/1033/rootDoc.ico differ
diff --git a/include/WTL/AppWiz/Files/Templates/1033/rootidl.h b/include/WTL/AppWiz/Files/Templates/1033/rootidl.h
new file mode 100644 (file)
index 0000000..fc5506c
--- /dev/null
@@ -0,0 +1,4 @@
+// [!output PROJECT_NAME].idl : IDL source for [!output PROJECT_NAME].exe
+//
+
+// Add interface and coclass declarations in this file
diff --git a/include/WTL/AppWiz/Files/Templates/1033/stdafx.cpp b/include/WTL/AppWiz/Files/Templates/1033/stdafx.cpp
new file mode 100644 (file)
index 0000000..5c1f92d
--- /dev/null
@@ -0,0 +1,18 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     [!output PROJECT_NAME].pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
+[!if WTL_COM_SERVER]
+
+#ifdef _ATL_STATIC_REGISTRY
+#include <statreg.h>
+#if (_ATL_VER < 0x0700)
+#include <statreg.cpp>
+#endif //(_ATL_VER < 0x0700)
+#endif //_ATL_STATIC_REGISTRY
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1033/stdafx.h b/include/WTL/AppWiz/Files/Templates/1033/stdafx.h
new file mode 100644 (file)
index 0000000..a765143
--- /dev/null
@@ -0,0 +1,114 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#pragma once
+
+// Change these values to use different versions
+#define WINVER         0x0500
+#define _WIN32_WINNT   0x0501
+#define _WIN32_IE      0x0501
+#define _RICHEDIT_VER  0x0200
+
+[!if WTL_COM_SERVER]
+#define _ATL_APARTMENT_THREADED
+
+[!endif]
+[!if WTL_USE_SDK_ATL3]
+// This project was generated for VC++ 2005 Express and ATL 3.0 from Platform SDK.
+// Comment out this line to build the project with different versions of VC++ and ATL.
+#define _WTL_SUPPORT_SDK_ATL3
+
+// Support for VS2005 Express & SDK ATL
+#ifdef _WTL_SUPPORT_SDK_ATL3
+  #define _CRT_SECURE_NO_DEPRECATE
+  #pragma conform(forScope, off)
+  #pragma comment(linker, "/NODEFAULTLIB:atlthunk.lib")
+#endif // _WTL_SUPPORT_SDK_ATL3
+
+[!endif]
+[!if WTL_USE_WDK_ATL71]
+// This project was generated for VC++ 2008 Express and ATL 7.1 from WDK.
+// Comment out this line to build the project with different versions of VC++ and ATL.
+#pragma comment(lib, "atlthunk.lib")
+
+[!endif]
+#include <atlbase.h>
+[!if WTL_USE_SDK_ATL3]
+
+// Support for VS2005 Express & SDK ATL
+#ifdef _WTL_SUPPORT_SDK_ATL3
+  namespace ATL
+  {
+       inline void * __stdcall __AllocStdCallThunk()
+       {
+               return ::HeapAlloc(::GetProcessHeap(), 0, sizeof(_stdcallthunk));
+       }
+
+       inline void __stdcall __FreeStdCallThunk(void *p)
+       {
+               ::HeapFree(::GetProcessHeap(), 0, p);
+       }
+  };
+#endif // _WTL_SUPPORT_SDK_ATL3
+
+[!endif]
+#include <atlapp.h>
+
+[!if WTL_COM_SERVER]
+extern CServerAppModule _Module;
+
+// This is here only to tell VC7 Class Wizard this is an ATL project
+#ifdef ___VC7_CLWIZ_ONLY___
+CComModule
+CExeModule
+#endif
+
+[!else]
+extern CAppModule _Module;
+
+[!endif]
+[!if WTL_ENABLE_AX || WTL_COM_SERVER]
+#include <atlcom.h>
+[!endif]
+[!if WTL_ENABLE_AX]
+#include <atlhost.h>
+[!endif]
+#include <atlwin.h>
+[!if WTL_ENABLE_AX]
+#include <atlctl.h>
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+[!if WTL_USE_CMDBAR]
+#include <atlctrlw.h>
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+#include <atlctrlx.h>
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+#include <atlctrlx.h>
+#include <atlsplit.h>
+[!endif]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_SCROLL]
+#include <atlscrl.h>
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_USE_EMBEDDED_MANIFEST]
+
+#if defined _M_IX86
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1033/toolbar.bmp b/include/WTL/AppWiz/Files/Templates/1033/toolbar.bmp
new file mode 100644 (file)
index 0000000..60f7a16
Binary files /dev/null and b/include/WTL/AppWiz/Files/Templates/1033/toolbar.bmp differ
diff --git a/include/WTL/AppWiz/Files/Templates/1041/AboutDlg.cpp b/include/WTL/AppWiz/Files/Templates/1041/AboutDlg.cpp
new file mode 100644 (file)
index 0000000..c1f285a
--- /dev/null
@@ -0,0 +1,20 @@
+// aboutdlg.cpp : implementation of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "aboutdlg.h"
+
+LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CenterWindow(GetParent());
+       return TRUE;
+}
+
+LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       EndDialog(wID);
+       return 0;
+}
diff --git a/include/WTL/AppWiz/Files/Templates/1041/AboutDlg.h b/include/WTL/AppWiz/Files/Templates/1041/AboutDlg.h
new file mode 100644 (file)
index 0000000..cca6b55
--- /dev/null
@@ -0,0 +1,42 @@
+// aboutdlg.h : interface of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CAboutDlg : public CDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTBOX };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+[!endif]
+};
diff --git a/include/WTL/AppWiz/Files/Templates/1041/ChildFrm.cpp b/include/WTL/AppWiz/Files/Templates/1041/ChildFrm.cpp
new file mode 100644 (file)
index 0000000..1f1bac5
--- /dev/null
@@ -0,0 +1,56 @@
+// [!output WTL_CHILD_FRAME_FILE].cpp : implementation of the [!output WTL_CHILD_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+[!if WTL_USE_VIEW]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+#include "[!output WTL_CHILD_FRAME_FILE].h"
+
+void [!output WTL_CHILD_FRAME_CLASS]::OnFinalMessage(HWND /*hWnd*/)
+{
+       delete this;
+}
+
+[!if WTL_USE_VIEW]
+LRESULT [!output WTL_CHILD_FRAME_CLASS]::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+[!if WTL_VIEWTYPE_FORM]
+       m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+       //TODO: Replace with a URL of your choice
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+       m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+       // replace with appropriate values for the app
+       m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+[!endif]
+
+       bHandled = FALSE;
+       return 1;
+}
+
+[!endif]
+LRESULT [!output WTL_CHILD_FRAME_CLASS]::OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+{
+       LPMSG pMsg = (LPMSG)lParam;
+
+[!if WTL_USE_VIEW]
+       if([!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+               return TRUE;
+
+       return m_view.PreTranslateMessage(pMsg);
+[!else]
+       return [!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+}
diff --git a/include/WTL/AppWiz/Files/Templates/1041/ChildFrm.h b/include/WTL/AppWiz/Files/Templates/1041/ChildFrm.h
new file mode 100644 (file)
index 0000000..dd1d742
--- /dev/null
@@ -0,0 +1,85 @@
+// [!output WTL_CHILD_FRAME_FILE].h : interface of the [!output WTL_CHILD_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class [!output WTL_CHILD_FRAME_CLASS] : public [!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MDICHILD)
+
+[!if WTL_USE_VIEW]
+       [!output WTL_VIEW_CLASS] m_view;
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual void OnFinalMessage(HWND /*hWnd*/);
+[!else]
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+[!endif]
+
+       BEGIN_MSG_MAP([!output WTL_CHILD_FRAME_CLASS])
+[!if WTL_USE_VIEW]
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+[!endif]
+               MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg)
+               CHAIN_MSG_MAP([!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_VIEW]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
+[!else]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+[!if WTL_VIEWTYPE_FORM]
+               m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+               //TODO: Replace with a URL of your choice
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+               m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               // replace with appropriate values for the app
+               m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+[!endif]
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LPMSG pMsg = (LPMSG)lParam;
+
+[!if WTL_USE_VIEW]
+               if([!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+[!else]
+               return [!output WTL_CHILD_FRAME_BASE_CLASS]<[!output WTL_CHILD_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+       }
+[!endif]
+};
diff --git a/include/WTL/AppWiz/Files/Templates/1041/Frame.cpp b/include/WTL/AppWiz/Files/Templates/1041/Frame.cpp
new file mode 100644 (file)
index 0000000..a2efa64
--- /dev/null
@@ -0,0 +1,391 @@
+// [!output WTL_FRAME_FILE].cpp : implmentation of the [!output WTL_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "aboutdlg.h"
+[!if WTL_USE_VIEW]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+[!if WTL_APPTYPE_MDI]
+#include "[!output WTL_CHILD_FRAME_FILE].h"
+[!endif]
+#include "[!output WTL_FRAME_FILE].h"
+
+BOOL [!output WTL_FRAME_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_APPTYPE_MDI]
+       if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+               return TRUE;
+
+       HWND hWnd = MDIGetActive();
+       if(hWnd != NULL)
+               return (BOOL)::SendMessage(hWnd, WM_FORWARDMSG, 0, (LPARAM)pMsg);
+
+       return FALSE;
+[!else]
+[!if WTL_USE_VIEW]
+       if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+               return TRUE;
+
+       return m_view.PreTranslateMessage(pMsg);
+[!else]
+       return [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+[!endif]
+}
+
+BOOL [!output WTL_FRAME_CLASS]::OnIdle()
+{
+[!if WTL_USE_TOOLBAR]
+       UIUpdateToolBar();
+[!endif]
+       return FALSE;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_REBAR]
+[!if WTL_USE_CMDBAR]
+       // create command bar window
+       HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+       // attach menu
+       m_CmdBar.AttachMenu(GetMenu());
+       // load command bar images
+       m_CmdBar.LoadImages(IDR_MAINFRAME);
+       // remove old menu
+       SetMenu(NULL);
+
+[!endif]
+       HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+       CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+[!if WTL_USE_CMDBAR]
+       AddSimpleReBarBand(hWndCmdBar);
+       AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+[!else]
+       AddSimpleReBarBand(hWndToolBar);
+[!endif]
+[!else]
+       CreateSimpleToolBar();
+[!endif]
+[!endif]
+[!if WTL_USE_STATUSBAR]
+
+       CreateSimpleStatusBar();
+[!endif]
+[!if WTL_APPTYPE_MDI]
+
+       CreateMDIClient();
+[!if WTL_USE_CMDBAR]
+       m_CmdBar.SetMDIClient(m_hWndMDIClient);
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+
+       m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+       //TODO: Replace with a URL of your choice
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+       m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+       // replace with appropriate values for the app
+       m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+
+       m_hWndClient = m_splitter.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+
+       m_pane.SetPaneContainerExtendedStyle(PANECNT_NOBORDER);
+       m_pane.Create(m_splitter, _T("Tree"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+       m_treeview.Create(m_pane, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE);
+       m_treeview.SetFont(AtlGetDefaultGuiFont());
+       m_pane.SetClient(m_treeview);
+[!if WTL_VIEWTYPE_FORM]
+
+       m_view.Create(m_splitter);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+       //TODO: Replace with a URL of your choice
+       m_view.Create(m_splitter, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+
+       m_view.Create(m_splitter, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+       m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+       // replace with appropriate values for the app
+       m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+
+       m_splitter.SetSplitterPanes(m_pane, m_view);
+       UpdateLayout();
+       m_splitter.SetSplitterPosPct(25);
+[!endif]
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_REBAR]
+
+       UIAddToolBar(hWndToolBar);
+[!else]
+
+       UIAddToolBar(m_hWndToolBar);
+[!endif]
+       UISetCheck(ID_VIEW_TOOLBAR, 1);
+[!endif]
+[!if WTL_USE_STATUSBAR]
+       UISetCheck(ID_VIEW_STATUS_BAR, 1);
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+       UISetCheck(ID_VIEW_TREEPANE, 1);
+[!endif]
+
+       // register object for message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->AddMessageFilter(this);
+       pLoop->AddIdleHandler(this);
+
+[!if WTL_APPTYPE_TABVIEW]
+[!if WTL_USE_CMDBAR]
+       CMenuHandle menuMain = m_CmdBar.GetMenu();
+[!else]
+       CMenuHandle menuMain = GetMenu();
+[!endif]
+       m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));
+
+[!endif]
+       return 0;
+}
+
+[!if WTL_COM_SERVER]
+LRESULT [!output WTL_FRAME_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.AttachMenu(NULL);
+
+[!endif]
+[!endif]
+       // unregister message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->RemoveMessageFilter(this);
+       pLoop->RemoveIdleHandler(this);
+
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+
+[!if WTL_APPTYPE_MTSDI]
+       ::PostQuitMessage(1);
+
+[!endif]
+       return 0;
+}
+
+[!else]
+LRESULT [!output WTL_FRAME_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.AttachMenu(NULL);
+
+[!endif]
+[!endif]
+       // unregister message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->RemoveMessageFilter(this);
+       pLoop->RemoveIdleHandler(this);
+
+       bHandled = FALSE;
+       return 1;
+}
+
+[!endif]
+LRESULT [!output WTL_FRAME_CLASS]::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       PostMessage(WM_CLOSE);
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+[!if WTL_APPTYPE_TABVIEW]
+       [!output WTL_VIEW_CLASS]* pView = new [!output WTL_VIEW_CLASS];
+[!if WTL_VIEWTYPE_FORM]
+       pView->Create(m_view);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+       //TODO: Replace with a URL of your choice
+       pView->Create(m_view, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+       pView->Create(m_view, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+       pView->SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+       // replace with appropriate values for the app
+       pView->SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+       m_view.AddPage(pView->m_hWnd, _T("Document"));
+
+[!endif]
+[!if WTL_APPTYPE_MDI]
+       [!output WTL_CHILD_FRAME_CLASS]* pChild = new [!output WTL_CHILD_FRAME_CLASS];
+       pChild->CreateEx(m_hWndClient);
+
+[!endif]
+       // TODO: add code to initialize document
+
+       return 0;
+}
+
+[!if WTL_APPTYPE_MTSDI]
+LRESULT [!output WTL_FRAME_CLASS]::OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
+       return 0;
+}
+
+[!endif]
+[!if WTL_USE_TOOLBAR]
+LRESULT [!output WTL_FRAME_CLASS]::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+[!if WTL_USE_REBAR]
+       static BOOL bVisible = TRUE;    // initially visible
+       bVisible = !bVisible;
+       CReBarCtrl rebar = m_hWndToolBar;
+[!if WTL_USE_CMDBAR]
+       int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);       // toolbar is 2nd added band
+[!else]
+       int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST);   // toolbar is first 1st band
+[!endif]
+       rebar.ShowBand(nBandIndex, bVisible);
+[!else]
+       BOOL bVisible = !::IsWindowVisible(m_hWndToolBar);
+       ::ShowWindow(m_hWndToolBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+[!endif]
+       UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+       UpdateLayout();
+       return 0;
+}
+
+[!endif]
+[!if WTL_USE_STATUSBAR]
+LRESULT [!output WTL_FRAME_CLASS]::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+       ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+       UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+       UpdateLayout();
+       return 0;
+}
+
+[!endif]
+LRESULT [!output WTL_FRAME_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CAboutDlg dlg;
+       dlg.DoModal();
+       return 0;
+}
+[!if WTL_APPTYPE_MDI]
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowCascade(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       MDICascade();
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowTile(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       MDITile();
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowArrangeIcons(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       MDIIconArrange();
+       return 0;
+}
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       int nActivePage = m_view.GetActivePage();
+       if(nActivePage != -1)
+               m_view.RemovePage(nActivePage);
+       else
+               ::MessageBeep((UINT)-1);
+
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       m_view.RemoveAllPages();
+
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       int nPage = wID - ID_WINDOW_TABFIRST;
+       m_view.SetActivePage(nPage);
+
+       return 0;
+}
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+
+LRESULT [!output WTL_FRAME_CLASS]::OnViewTreePane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       bool bShow = (m_splitter.GetSinglePaneMode() != SPLIT_PANE_NONE);
+       m_splitter.SetSinglePaneMode(bShow ? SPLIT_PANE_NONE : SPLIT_PANE_RIGHT);
+       UISetCheck(ID_VIEW_TREEPANE, bShow);
+
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnTreePaneClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND hWndCtl, BOOL& /*bHandled*/)
+{
+       if(hWndCtl == m_pane.m_hWnd)
+       {
+               m_splitter.SetSinglePaneMode(SPLIT_PANE_RIGHT);
+               UISetCheck(ID_VIEW_TREEPANE, 0);
+       }
+
+       return 0;
+}
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1041/Frame.h b/include/WTL/AppWiz/Files/Templates/1041/Frame.h
new file mode 100644 (file)
index 0000000..7fba4fc
--- /dev/null
@@ -0,0 +1,543 @@
+// [!output WTL_FRAME_FILE].h : interface of the [!output WTL_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_APPTYPE_TABVIEW]
+#define WINDOW_MENU_POSITION   3
+
+[!endif]
+class [!output WTL_FRAME_CLASS] : public [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>, public CUpdateUI<[!output WTL_FRAME_CLASS]>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
+
+[!if WTL_APPTYPE_TABVIEW]
+       CTabView m_view;
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+       CSplitterWindow m_splitter;
+       CPaneContainer m_pane;
+       CTreeViewCtrl m_treeview;
+       [!output WTL_VIEW_CLASS] m_view;
+[!endif]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+       [!output WTL_VIEW_CLASS] m_view;
+
+[!endif]
+[!endif]
+[!if WTL_USE_CMDBAR]
+[!if WTL_APPTYPE_MDI]
+       CMDICommandBarCtrl m_CmdBar;
+
+[!else]
+       CCommandBarCtrl m_CmdBar;
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_APPTYPE_MDI]
+               if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               HWND hWnd = MDIGetActive();
+               if(hWnd != NULL)
+                       return (BOOL)::SendMessage(hWnd, WM_FORWARDMSG, 0, (LPARAM)pMsg);
+
+               return FALSE;
+[!else]
+[!if WTL_USE_VIEW]
+               if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+[!else]
+               return [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+[!endif]
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL OnIdle();
+[!else]
+       virtual BOOL OnIdle()
+       {
+[!if WTL_USE_TOOLBAR]
+               UIUpdateToolBar();
+[!endif]
+               return FALSE;
+       }
+[!endif]
+
+       BEGIN_UPDATE_UI_MAP([!output WTL_FRAME_CLASS])
+[!if WTL_USE_TOOLBAR]
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+               UPDATE_ELEMENT(ID_VIEW_TREEPANE, UPDUI_MENUPOPUP)
+[!endif]
+       END_UPDATE_UI_MAP()
+
+       BEGIN_MSG_MAP([!output WTL_FRAME_CLASS])
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+[!if WTL_APPTYPE_MTSDI]
+               COMMAND_ID_HANDLER(ID_FILE_NEW_WINDOW, OnFileNewWindow)
+[!endif]
+[!if WTL_USE_TOOLBAR]
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+[!if WTL_APPTYPE_MDI]
+               COMMAND_ID_HANDLER(ID_WINDOW_CASCADE, OnWindowCascade)
+               COMMAND_ID_HANDLER(ID_WINDOW_TILE_HORZ, OnWindowTile)
+               COMMAND_ID_HANDLER(ID_WINDOW_ARRANGE, OnWindowArrangeIcons)
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+               COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose)
+               COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll)
+               COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+               COMMAND_ID_HANDLER(ID_VIEW_TREEPANE, OnViewTreePane)
+               COMMAND_ID_HANDLER(ID_PANE_CLOSE, OnTreePaneClose)
+[!endif]
+               CHAIN_MSG_MAP(CUpdateUI<[!output WTL_FRAME_CLASS]>)
+               CHAIN_MSG_MAP([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_REBAR]
+[!if WTL_USE_CMDBAR]
+               // create command bar window
+               HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+               // attach menu
+               m_CmdBar.AttachMenu(GetMenu());
+               // load command bar images
+               m_CmdBar.LoadImages(IDR_MAINFRAME);
+               // remove old menu
+               SetMenu(NULL);
+
+[!endif]
+               HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+               CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+[!if WTL_USE_CMDBAR]
+               AddSimpleReBarBand(hWndCmdBar);
+               AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+[!else]
+               AddSimpleReBarBand(hWndToolBar);
+[!endif]
+[!else]
+               CreateSimpleToolBar();
+[!endif]
+[!endif]
+[!if WTL_USE_STATUSBAR]
+
+               CreateSimpleStatusBar();
+[!endif]
+[!if WTL_APPTYPE_MDI]
+
+               CreateMDIClient();
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.SetMDIClient(m_hWndMDIClient);
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+
+               m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+               //TODO: Replace with a URL of your choice
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+               m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               // replace with appropriate values for the app
+               m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+
+               m_hWndClient = m_splitter.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+
+               m_pane.SetPaneContainerExtendedStyle(PANECNT_NOBORDER);
+               m_pane.Create(m_splitter, _T("Tree"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+               m_treeview.Create(m_pane, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE);
+               m_treeview.SetFont(AtlGetDefaultGuiFont());
+               m_pane.SetClient(m_treeview);
+[!if WTL_VIEWTYPE_FORM]
+
+               m_view.Create(m_splitter);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+               //TODO: Replace with a URL of your choice
+               m_view.Create(m_splitter, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+
+               m_view.Create(m_splitter, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+               m_view.SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               // replace with appropriate values for the app
+               m_view.SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+
+               m_splitter.SetSplitterPanes(m_pane, m_view);
+               UpdateLayout();
+               m_splitter.SetSplitterPosPct(25);
+[!endif]
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_REBAR]
+
+               UIAddToolBar(hWndToolBar);
+[!else]
+
+               UIAddToolBar(m_hWndToolBar);
+[!endif]
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+               UISetCheck(ID_VIEW_TREEPANE, 1);
+[!endif]
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+[!if WTL_APPTYPE_TABVIEW]
+[!if WTL_USE_CMDBAR]
+               CMenuHandle menuMain = m_CmdBar.GetMenu();
+[!else]
+               CMenuHandle menuMain = GetMenu();
+[!endif]
+               m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));
+
+[!endif]
+               return 0;
+       }
+[!endif]
+[!if WTL_COM_SERVER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.AttachMenu(NULL);
+
+[!endif]
+[!endif]
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+
+[!if WTL_APPTYPE_MTSDI]
+               ::PostQuitMessage(1);
+
+[!endif]
+               return 0;
+       }
+[!endif]
+[!else]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
+[!else]
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CMDBAR]
+               m_CmdBar.AttachMenu(NULL);
+
+[!endif]
+[!endif]
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+
+               bHandled = FALSE;
+               return 1;
+       }
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_APPTYPE_TABVIEW]
+               [!output WTL_VIEW_CLASS]* pView = new [!output WTL_VIEW_CLASS];
+[!if WTL_VIEWTYPE_FORM]
+               pView->Create(m_view);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+               //TODO: Replace with a URL of your choice
+               pView->Create(m_view, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!else]
+               pView->Create(m_view, rcDefault, NULL, [!output WTL_VIEW_STYLES], [!output WTL_VIEW_EX_STYLES]);
+[!endif]
+[!if WTL_VIEWTYPE_LISTBOX || WTL_VIEWTYPE_EDIT || WTL_VIEWTYPE_LISTVIEW || WTL_VIEWTYPE_TREEVIEW || WTL_VIEWTYPE_RICHEDIT]
+               pView->SetFont(AtlGetDefaultGuiFont());
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               // replace with appropriate values for the app
+               pView->SetScrollSize(2000, 1000);
+[!endif]
+[!endif]
+               m_view.AddPage(pView->m_hWnd, _T("Document"));
+
+[!endif]
+[!if WTL_APPTYPE_MDI]
+               [!output WTL_CHILD_FRAME_CLASS]* pChild = new [!output WTL_CHILD_FRAME_CLASS];
+               pChild->CreateEx(m_hWndClient);
+
+[!endif]
+               // TODO: add code to initialize document
+
+               return 0;
+       }
+[!endif]
+[!if WTL_APPTYPE_MTSDI]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
+               return 0;
+       }
+[!endif]
+[!endif]
+[!if WTL_USE_TOOLBAR]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_USE_REBAR]
+               static BOOL bVisible = TRUE;    // initially visible
+               bVisible = !bVisible;
+               CReBarCtrl rebar = m_hWndToolBar;
+[!if WTL_USE_CMDBAR]
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);       // toolbar is 2nd added band
+[!else]
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST);   // toolbar is first 1st band
+[!endif]
+               rebar.ShowBand(nBandIndex, bVisible);
+[!else]
+               BOOL bVisible = !::IsWindowVisible(m_hWndToolBar);
+               ::ShowWindow(m_hWndToolBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+[!endif]
+               UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+[!endif]
+[!endif]
+[!if WTL_USE_STATUSBAR]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+[!endif]
+[!if WTL_APPTYPE_MDI]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowCascade(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowCascade(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               MDICascade();
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowTile(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowTile(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               MDITile();
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowArrangeIcons(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowArrangeIcons(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               MDIIconArrange();
+               return 0;
+       }
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               int nActivePage = m_view.GetActivePage();
+               if(nActivePage != -1)
+                       m_view.RemovePage(nActivePage);
+               else
+                       ::MessageBeep((UINT)-1);
+
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               m_view.RemoveAllPages();
+
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       int nPage = wID - ID_WINDOW_TABFIRST;
+       m_view.SetActivePage(nPage);
+
+       return 0;
+}
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnViewTreePane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnViewTreePane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               bool bShow = (m_splitter.GetSinglePaneMode() != SPLIT_PANE_NONE);
+               m_splitter.SetSinglePaneMode(bShow ? SPLIT_PANE_NONE : SPLIT_PANE_RIGHT);
+               UISetCheck(ID_VIEW_TREEPANE, bShow);
+
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnTreePaneClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND hWndCtl, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnTreePaneClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND hWndCtl, BOOL& /*bHandled*/)
+       {
+               if(hWndCtl == m_pane.m_hWnd)
+               {
+                       m_splitter.SetSinglePaneMode(SPLIT_PANE_RIGHT);
+                       UISetCheck(ID_VIEW_TREEPANE, 0);
+               }
+
+               return 0;
+       }
+[!endif]
+[!endif]
+};
diff --git a/include/WTL/AppWiz/Files/Templates/1041/MainDlg.cpp b/include/WTL/AppWiz/Files/Templates/1041/MainDlg.cpp
new file mode 100644 (file)
index 0000000..5e16279
--- /dev/null
@@ -0,0 +1,167 @@
+// [!output WTL_MAINDLG_FILE].cpp : implementation of the [!output WTL_MAINDLG_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+#include "aboutdlg.h"
+[!endif]
+#include "[!output WTL_MAINDLG_FILE].h"
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+BOOL [!output WTL_MAINDLG_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_HOST_AX]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       HWND hWndCtl = ::GetFocus();
+       if(IsChild(hWndCtl))
+       {
+               // find a direct child of the dialog from the window that has focus
+               while(::GetParent(hWndCtl) != m_hWnd)
+                       hWndCtl = ::GetParent(hWndCtl);
+
+               // give control a chance to translate this message
+               if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                       return TRUE;
+       }
+
+[!endif]
+       return CWindow::IsDialogMessage(pMsg);
+}
+
+BOOL [!output WTL_MAINDLG_CLASS]::OnIdle()
+{
+       return FALSE;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // center the dialog on the screen
+       CenterWindow();
+
+       // set icons
+       HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+       SetIcon(hIcon, TRUE);
+       HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+       SetIcon(hIconSmall, FALSE);
+
+       // register object for message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->AddMessageFilter(this);
+       pLoop->AddIdleHandler(this);
+
+       UIAddChildWindowContainer(m_hWnd);
+
+       return TRUE;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // unregister message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->RemoveMessageFilter(this);
+       pLoop->RemoveIdleHandler(this);
+[!if WTL_COM_SERVER]
+
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+[!endif]
+
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CAboutDlg dlg;
+       dlg.DoModal();
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: Add validation code 
+       CloseDialog(wID);
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CloseDialog(wID);
+       return 0;
+}
+
+void [!output WTL_MAINDLG_CLASS]::CloseDialog(int nVal)
+{
+       DestroyWindow();
+       ::PostQuitMessage(nVal);
+}
+[!endif]
+[!if WTL_APPTYPE_DLG && WTL_APPTYPE_DLG_MODAL]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+
+[!endif]
+       // center the dialog on the screen
+       CenterWindow();
+
+       // set icons
+       HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+       SetIcon(hIcon, TRUE);
+       HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+       SetIcon(hIconSmall, FALSE);
+
+       return TRUE;
+}
+
+[!if WTL_COM_SERVER]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+       return 0;
+}
+
+[!endif]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CSimpleDialog<IDD_ABOUTBOX, FALSE> dlg;
+       dlg.DoModal();
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: Add validation code 
+       EndDialog(wID);
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       EndDialog(wID);
+       return 0;
+}
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1041/MainDlg.h b/include/WTL/AppWiz/Files/Templates/1041/MainDlg.h
new file mode 100644 (file)
index 0000000..54e6f41
--- /dev/null
@@ -0,0 +1,259 @@
+// [!output WTL_MAINDLG_FILE].h : interface of the [!output WTL_MAINDLG_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+class [!output WTL_MAINDLG_CLASS] : public [!output WTL_MAINDLG_BASE_CLASS]<[!output WTL_MAINDLG_CLASS]>, public CUpdateUI<[!output WTL_MAINDLG_CLASS]>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       enum { IDD = IDD_MAINDLG };
+
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_HOST_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+[!endif]
+               return CWindow::IsDialogMessage(pMsg);
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL OnIdle();
+[!else]
+       virtual BOOL OnIdle()
+       {
+               return FALSE;
+       }
+[!endif]
+
+       BEGIN_UPDATE_UI_MAP([!output WTL_MAINDLG_CLASS])
+       END_UPDATE_UI_MAP()
+
+       BEGIN_MSG_MAP([!output WTL_MAINDLG_CLASS])
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_ID_HANDLER(IDOK, OnOK)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // center the dialog on the screen
+               CenterWindow();
+
+               // set icons
+               HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+               SetIcon(hIcon, TRUE);
+               HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+               SetIcon(hIconSmall, FALSE);
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               UIAddChildWindowContainer(m_hWnd);
+
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+[!if WTL_COM_SERVER]
+
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+[!endif]
+
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: Add validation code 
+               CloseDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CloseDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+       void CloseDialog(int nVal);
+[!else]
+       void CloseDialog(int nVal)
+       {
+               DestroyWindow();
+               ::PostQuitMessage(nVal);
+       }
+[!endif]
+};
+[!endif]
+[!if WTL_APPTYPE_DLG && WTL_APPTYPE_DLG_MODAL]
+class [!output WTL_MAINDLG_CLASS] : public [!output WTL_MAINDLG_BASE_CLASS]<[!output WTL_MAINDLG_CLASS]>
+{
+public:
+       enum { IDD = IDD_MAINDLG };
+
+       BEGIN_MSG_MAP([!output WTL_MAINDLG_CLASS])
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+[!if WTL_COM_SERVER]
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_ID_HANDLER(IDOK, OnOK)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_COM_SERVER]
+               _Module.Lock();
+
+[!endif]
+               // center the dialog on the screen
+               CenterWindow();
+
+               // set icons
+               HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+               SetIcon(hIcon, TRUE);
+               HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+               SetIcon(hIconSmall, FALSE);
+
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_COM_SERVER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CSimpleDialog<IDD_ABOUTBOX, FALSE> dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: Add validation code 
+               EndDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+[!endif]
+};
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1041/View.cpp b/include/WTL/AppWiz/Files/Templates/1041/View.cpp
new file mode 100644 (file)
index 0000000..9798d3e
--- /dev/null
@@ -0,0 +1,63 @@
+// [!output WTL_VIEW_FILE].cpp : implementation of the [!output WTL_VIEW_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "[!output WTL_VIEW_FILE].h"
+
+BOOL [!output WTL_VIEW_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_HOST_AX]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       HWND hWndCtl = ::GetFocus();
+       if(IsChild(hWndCtl))
+       {
+               // find a direct child of the dialog from the window that has focus
+               while(::GetParent(hWndCtl) != m_hWnd)
+                       hWndCtl = ::GetParent(hWndCtl);
+
+               // give control a chance to translate this message
+               if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                       return TRUE;
+       }
+
+[!endif]
+[!if WTL_VIEWTYPE_HTML]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       // give HTML page a chance to translate this message
+       return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+       return CWindow::IsDialogMessage(pMsg);
+[!else]
+       pMsg;
+       return FALSE;
+[!endif]
+[!endif]
+}
+[!if WTL_VIEWTYPE_SCROLL]
+
+void [!output WTL_VIEW_CLASS]::DoPaint(CDCHandle dc)
+{
+       //TODO: Add your drawing code here
+}
+[!endif]
+[!if WTL_VIEWTYPE_GENERIC]
+
+LRESULT [!output WTL_VIEW_CLASS]::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CPaintDC dc(m_hWnd);
+
+       //TODO: Add your drawing code here
+
+       return 0;
+}
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1041/View.h b/include/WTL/AppWiz/Files/Templates/1041/View.h
new file mode 100644 (file)
index 0000000..75207d0
--- /dev/null
@@ -0,0 +1,107 @@
+// [!output WTL_VIEW_FILE].h : interface of the [!output WTL_VIEW_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_VIEWTYPE_GENERIC || WTL_VIEWTYPE_FORM || WTL_VIEWTYPE_SCROLL]
+class [!output WTL_VIEW_CLASS] : public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS]>
+[!else]
+class [!output WTL_VIEW_CLASS] : public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS], [!output WTL_VIEW_BASE]>
+[!endif]
+{
+public:
+[!if WTL_VIEWTYPE_GENERIC || WTL_VIEWTYPE_SCROLL]
+       DECLARE_WND_CLASS(NULL)
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+       enum { IDD = IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM };
+[!else]
+       DECLARE_WND_SUPERCLASS(NULL, [!output WTL_VIEW_BASE]::GetWndClassName())
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+       BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_HOST_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+[!endif]
+[!if WTL_VIEWTYPE_HTML]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               // give HTML page a chance to translate this message
+               return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+               return CWindow::IsDialogMessage(pMsg);
+[!else]
+               pMsg;
+               return FALSE;
+[!endif]
+[!endif]
+       }
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+[!if WTL_USE_CPP_FILES]
+
+       void DoPaint(CDCHandle dc);
+[!else]
+
+       void DoPaint(CDCHandle dc)
+       {
+               //TODO: Add your drawing code here
+       }
+[!endif]
+[!endif]
+
+       BEGIN_MSG_MAP([!output WTL_VIEW_CLASS])
+[!if WTL_VIEWTYPE_GENERIC]
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+[!endif]
+[!if WTL_VIEWTYPE_SCROLL]
+               CHAIN_MSG_MAP([!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS]>)
+[!endif]
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+[!if WTL_VIEWTYPE_GENERIC]
+[!if WTL_USE_CPP_FILES]
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CPaintDC dc(m_hWnd);
+
+               //TODO: Add your drawing code here
+
+               return 0;
+       }
+[!endif]
+[!endif]
+};
diff --git a/include/WTL/AppWiz/Files/Templates/1041/resource.h b/include/WTL/AppWiz/Files/Templates/1041/resource.h
new file mode 100644 (file)
index 0000000..5c2fed9
--- /dev/null
@@ -0,0 +1,59 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by [!output PROJECT_NAME].RC
+//
+
+[!if WTL_COM_SERVER]
+#define IDS_PROJNAME                           100
+#define IDR_[!output UPPERCASE_SAFE_PROJECT_NAME]      100
+[!endif]
+
+#define IDD_ABOUTBOX                           100
+#define IDR_MAINFRAME                          128
+//#define IDR_[!output UPPERCASE_SAFE_PROJECT_NAME]TYPE        129
+[!if WTL_APPTYPE_MDI]
+#define IDR_MDICHILD                           129
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 130
+[!endif]
+[!endif]
+[!else]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_TABVIEW || WTL_APPTYPE_EXPLORER]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 129
+[!endif]
+[!endif]
+[!else]
+[!if WTL_APPTYPE_DLG]
+#define IDD_MAINDLG                            129
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 130
+[!endif]
+[!endif]
+#define ID_FILE_NEW_WINDOW                     32771
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+#define ID_WINDOW_CLOSE                                32772
+#define ID_WINDOW_CLOSE_ALL                    32773
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+#define ID_VIEW_TREEPANE                       32774
+[!endif]
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE       201
+#define _APS_NEXT_CONTROL_VALUE                1000
+#define _APS_NEXT_SYMED_VALUE          101
+#define _APS_NEXT_COMMAND_VALUE                32775
+#endif
+#endif
diff --git a/include/WTL/AppWiz/Files/Templates/1041/root.cpp b/include/WTL/AppWiz/Files/Templates/1041/root.cpp
new file mode 100644 (file)
index 0000000..b82d19f
--- /dev/null
@@ -0,0 +1,376 @@
+// [!output PROJECT_NAME].cpp : main source file for [!output PROJECT_NAME].exe
+//
+
+#include "stdafx.h"
+[!if !WTL_USE_CPP_FILES]
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+[!if WTL_USE_CMDBAR]
+#include <atlctrlw.h>
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+#include <atlctrlx.h>
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+#include <atlctrlx.h>
+#include <atlsplit.h>
+[!endif]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_SCROLL]
+#include <atlscrl.h>
+[!endif]
+[!endif]
+[!endif]
+
+#include "resource.h"
+
+[!if WTL_COM_SERVER]
+// Note: Proxy/Stub Information
+//             To build a separate proxy/stub DLL, 
+//             run nmake -f [!output PROJECT_NAME]ps.mk in the project directory.
+#include "initguid.h"
+#include "[!output PROJECT_NAME].h"
+#include "[!output PROJECT_NAME]_i.c"
+
+[!endif]
+[!if WTL_USE_VIEW]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+[!if !WTL_APPTYPE_DLG_MODAL]
+#include "aboutdlg.h"
+[!endif]
+[!if WTL_APPTYPE_MDI]
+#include "[!output WTL_CHILD_FRAME_FILE].h"
+[!endif]
+[!if WTL_APPTYPE_DLG]
+#include "[!output WTL_MAINDLG_FILE].h"
+[!else]
+#include "[!output WTL_FRAME_FILE].h"
+[!endif]
+[!if WTL_COM_SERVER]
+
+CServerAppModule _Module;
+
+BEGIN_OBJECT_MAP(ObjectMap)
+END_OBJECT_MAP()
+[!else]
+
+CAppModule _Module;
+[!endif]
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       [!output WTL_MAINDLG_CLASS] dlgMain;
+
+       if(dlgMain.Create(NULL) == NULL)
+       {
+               ATLTRACE(_T("Main dialog creation failed!\n"));
+               return 0;
+       }
+
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+[!endif]
+       dlgMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+[!endif]
+[!if !WTL_APPTYPE_DLG && WTL_APPTYPE_MTSDI]
+
+class C[!output SAFE_PROJECT_NAME]ThreadManager
+{
+public:
+       // thread init param
+       struct _RunData
+       {
+               LPTSTR lpstrCmdLine;
+               int nCmdShow;
+       };
+
+       // thread proc
+       static DWORD WINAPI RunThread(LPVOID lpData)
+       {
+               CMessageLoop theLoop;
+               _Module.AddMessageLoop(&theLoop);
+
+               _RunData* pData = (_RunData*)lpData;
+               [!output WTL_FRAME_CLASS] wndFrame;
+
+               if(wndFrame.CreateEx() == NULL)
+               {
+                       ATLTRACE(_T("Frame window creation failed!\n"));
+                       return 0;
+               }
+
+[!if WTL_COM_SERVER]
+               _Module.Lock();
+[!endif]
+               wndFrame.ShowWindow(pData->nCmdShow);
+               ::SetForegroundWindow(wndFrame);        // Win95 needs this
+               delete pData;
+
+               int nRet = theLoop.Run();
+
+               _Module.RemoveMessageLoop();
+               return nRet;
+       }
+
+       DWORD m_dwCount;
+       HANDLE m_arrThreadHandles[MAXIMUM_WAIT_OBJECTS - 1];
+
+       C[!output SAFE_PROJECT_NAME]ThreadManager() : m_dwCount(0)
+       { }
+
+// Operations
+       DWORD AddThread(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               if(m_dwCount == (MAXIMUM_WAIT_OBJECTS - 1))
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create ANY MORE threads!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       return 0;
+               }
+
+               _RunData* pData = new _RunData;
+               pData->lpstrCmdLine = lpstrCmdLine;
+               pData->nCmdShow = nCmdShow;
+               DWORD dwThreadID;
+               HANDLE hThread = ::CreateThread(NULL, 0, RunThread, pData, 0, &dwThreadID);
+               if(hThread == NULL)
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create thread!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       return 0;
+               }
+
+               m_arrThreadHandles[m_dwCount] = hThread;
+               m_dwCount++;
+               return dwThreadID;
+       }
+
+       void RemoveThread(DWORD dwIndex)
+       {
+               ::CloseHandle(m_arrThreadHandles[dwIndex]);
+               if(dwIndex != (m_dwCount - 1))
+                       m_arrThreadHandles[dwIndex] = m_arrThreadHandles[m_dwCount - 1];
+               m_dwCount--;
+       }
+
+       int Run(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               MSG msg;
+               // force message queue to be created
+               ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+
+               AddThread(lpstrCmdLine, nCmdShow);
+
+               int nRet = m_dwCount;
+               DWORD dwRet;
+               while(m_dwCount > 0)
+               {
+                       dwRet = ::MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles, FALSE, INFINITE, QS_ALLINPUT);
+
+                       if(dwRet == 0xFFFFFFFF)
+                       {
+                               ::MessageBox(NULL, _T("ERROR: Wait for multiple objects failed!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       }
+                       else if(dwRet >= WAIT_OBJECT_0 && dwRet <= (WAIT_OBJECT_0 + m_dwCount - 1))
+                       {
+                               RemoveThread(dwRet - WAIT_OBJECT_0);
+                       }
+                       else if(dwRet == (WAIT_OBJECT_0 + m_dwCount))
+                       {
+                               if(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+                               {
+                                       if(msg.message == WM_USER)
+                                               AddThread(_T(""), SW_SHOWNORMAL);
+                               }
+                       }
+                       else
+                       {
+                               ::MessageBeep((UINT)-1);
+                       }
+               }
+
+               return nRet;
+       }
+};
+[!endif]
+[!if !WTL_APPTYPE_DLG && !WTL_APPTYPE_MTSDI]
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       [!output WTL_FRAME_CLASS] wndMain;
+
+       if(wndMain.CreateEx() == NULL)
+       {
+               ATLTRACE(_T("Main window creation failed!\n"));
+               return 0;
+       }
+
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+[!endif]
+       wndMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+[!endif]
+[!if !WTL_APPTYPE_DLG_MODAL]
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+[!else]
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)
+[!endif]
+{
+       HRESULT hRes = ::CoInitialize(NULL);
+// If you are running on NT 4.0 or higher you can use the following call instead to 
+// make the EXE free threaded. This means that calls come in on a random RPC thread.
+//     HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
+       ::DefWindowProc(NULL, 0, 0, 0L);
+
+[!if !WTL_USE_TOOLBAR || !WTL_USE_REBAR]
+       AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls
+[!else]
+       AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);      // add flags to support other controls
+[!endif]
+[!if WTL_COM_SERVER]
+
+       GUID guid;
+       hRes = _Module.Init(ObjectMap, hInstance, &guid);
+       ATLASSERT(SUCCEEDED(hRes));
+
+[!else]
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+[!endif]
+[!if WTL_USE_VIEW && WTL_VIEWTYPE_RICHEDIT]
+       HMODULE hInstRich = ::LoadLibrary(CRichEditCtrl::GetLibraryName());
+       ATLASSERT(hInstRich != NULL);
+
+[!endif]
+[!if WTL_ENABLE_AX]
+       AtlAxWinInit();
+
+[!endif]
+[!if WTL_COM_SERVER]
+       // Parse command line, register or unregister or run the server
+       int nRet = 0;
+       TCHAR szTokens[] = _T("-/");
+       bool bRun = true;
+       bool bAutomation = false;
+
+       LPCTSTR lpszToken = _Module.FindOneOf(::GetCommandLine(), szTokens);
+       while(lpszToken != NULL)
+       {
+               if(lstrcmpi(lpszToken, _T("UnregServer")) == 0)
+               {
+                       _Module.UpdateRegistryFromResource(IDR_[!output UPPERCASE_SAFE_PROJECT_NAME], FALSE);
+                       nRet = _Module.UnregisterServer(TRUE);
+                       bRun = false;
+                       break;
+               }
+               else if(lstrcmpi(lpszToken, _T("RegServer")) == 0)
+               {
+                       _Module.UpdateRegistryFromResource(IDR_[!output UPPERCASE_SAFE_PROJECT_NAME], TRUE);
+                       nRet = _Module.RegisterServer(TRUE);
+                       bRun = false;
+                       break;
+               }
+               else if((lstrcmpi(lpszToken, _T("Automation")) == 0) ||
+                       (lstrcmpi(lpszToken, _T("Embedding")) == 0))
+               {
+                       bAutomation = true;
+                       break;
+               }
+               lpszToken = _Module.FindOneOf(lpszToken, szTokens);
+       }
+
+       if(bRun)
+       {
+               _Module.StartMonitor();
+               hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
+               ATLASSERT(SUCCEEDED(hRes));
+               hRes = ::CoResumeClassObjects();
+               ATLASSERT(SUCCEEDED(hRes));
+
+               if(bAutomation)
+               {
+                       CMessageLoop theLoop;
+                       nRet = theLoop.Run();
+               }
+               else
+[!if WTL_APPTYPE_DLG_MODAL]
+               {
+                       [!output WTL_MAINDLG_CLASS] dlgMain;
+                       nRet = dlgMain.DoModal();
+               }
+[!else]
+[!if WTL_APPTYPE_MTSDI]
+               {
+                       C[!output SAFE_PROJECT_NAME]ThreadManager mgr;
+                       nRet = mgr.Run(lpstrCmdLine, nCmdShow);
+               }
+[!else]
+               {
+                       nRet = Run(lpstrCmdLine, nCmdShow);
+               }
+[!endif]
+[!endif]
+
+               _Module.RevokeClassObjects();
+               ::Sleep(_Module.m_dwPause);
+       }
+[!else]
+[!if WTL_APPTYPE_DLG_MODAL]
+       int nRet = 0;
+       // BLOCK: Run application
+       {
+               [!output WTL_MAINDLG_CLASS] dlgMain;
+               nRet = dlgMain.DoModal();
+       }
+[!else]
+[!if WTL_APPTYPE_MTSDI]
+       int nRet = 0;
+       // BLOCK: Run application
+       {
+               C[!output SAFE_PROJECT_NAME]ThreadManager mgr;
+               nRet = mgr.Run(lpstrCmdLine, nCmdShow);
+       }
+[!else]
+       int nRet = Run(lpstrCmdLine, nCmdShow);
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_RICHEDIT]
+
+       ::FreeLibrary(hInstRich);
+[!endif]
+[!endif]
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/AppWiz/Files/Templates/1041/root.h b/include/WTL/AppWiz/Files/Templates/1041/root.h
new file mode 100644 (file)
index 0000000..0c8afa9
--- /dev/null
@@ -0,0 +1 @@
+// [!output PROJECT_NAME].h
diff --git a/include/WTL/AppWiz/Files/Templates/1041/root.ico b/include/WTL/AppWiz/Files/Templates/1041/root.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/AppWiz/Files/Templates/1041/root.ico differ
diff --git a/include/WTL/AppWiz/Files/Templates/1041/rootDoc.ico b/include/WTL/AppWiz/Files/Templates/1041/rootDoc.ico
new file mode 100644 (file)
index 0000000..af5edfa
Binary files /dev/null and b/include/WTL/AppWiz/Files/Templates/1041/rootDoc.ico differ
diff --git a/include/WTL/AppWiz/Files/Templates/1041/rootidl.h b/include/WTL/AppWiz/Files/Templates/1041/rootidl.h
new file mode 100644 (file)
index 0000000..fc5506c
--- /dev/null
@@ -0,0 +1,4 @@
+// [!output PROJECT_NAME].idl : IDL source for [!output PROJECT_NAME].exe
+//
+
+// Add interface and coclass declarations in this file
diff --git a/include/WTL/AppWiz/Files/Templates/1041/stdafx.cpp b/include/WTL/AppWiz/Files/Templates/1041/stdafx.cpp
new file mode 100644 (file)
index 0000000..5c1f92d
--- /dev/null
@@ -0,0 +1,18 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     [!output PROJECT_NAME].pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
+[!if WTL_COM_SERVER]
+
+#ifdef _ATL_STATIC_REGISTRY
+#include <statreg.h>
+#if (_ATL_VER < 0x0700)
+#include <statreg.cpp>
+#endif //(_ATL_VER < 0x0700)
+#endif //_ATL_STATIC_REGISTRY
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1041/stdafx.h b/include/WTL/AppWiz/Files/Templates/1041/stdafx.h
new file mode 100644 (file)
index 0000000..a765143
--- /dev/null
@@ -0,0 +1,114 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#pragma once
+
+// Change these values to use different versions
+#define WINVER         0x0500
+#define _WIN32_WINNT   0x0501
+#define _WIN32_IE      0x0501
+#define _RICHEDIT_VER  0x0200
+
+[!if WTL_COM_SERVER]
+#define _ATL_APARTMENT_THREADED
+
+[!endif]
+[!if WTL_USE_SDK_ATL3]
+// This project was generated for VC++ 2005 Express and ATL 3.0 from Platform SDK.
+// Comment out this line to build the project with different versions of VC++ and ATL.
+#define _WTL_SUPPORT_SDK_ATL3
+
+// Support for VS2005 Express & SDK ATL
+#ifdef _WTL_SUPPORT_SDK_ATL3
+  #define _CRT_SECURE_NO_DEPRECATE
+  #pragma conform(forScope, off)
+  #pragma comment(linker, "/NODEFAULTLIB:atlthunk.lib")
+#endif // _WTL_SUPPORT_SDK_ATL3
+
+[!endif]
+[!if WTL_USE_WDK_ATL71]
+// This project was generated for VC++ 2008 Express and ATL 7.1 from WDK.
+// Comment out this line to build the project with different versions of VC++ and ATL.
+#pragma comment(lib, "atlthunk.lib")
+
+[!endif]
+#include <atlbase.h>
+[!if WTL_USE_SDK_ATL3]
+
+// Support for VS2005 Express & SDK ATL
+#ifdef _WTL_SUPPORT_SDK_ATL3
+  namespace ATL
+  {
+       inline void * __stdcall __AllocStdCallThunk()
+       {
+               return ::HeapAlloc(::GetProcessHeap(), 0, sizeof(_stdcallthunk));
+       }
+
+       inline void __stdcall __FreeStdCallThunk(void *p)
+       {
+               ::HeapFree(::GetProcessHeap(), 0, p);
+       }
+  };
+#endif // _WTL_SUPPORT_SDK_ATL3
+
+[!endif]
+#include <atlapp.h>
+
+[!if WTL_COM_SERVER]
+extern CServerAppModule _Module;
+
+// This is here only to tell VC7 Class Wizard this is an ATL project
+#ifdef ___VC7_CLWIZ_ONLY___
+CComModule
+CExeModule
+#endif
+
+[!else]
+extern CAppModule _Module;
+
+[!endif]
+[!if WTL_ENABLE_AX || WTL_COM_SERVER]
+#include <atlcom.h>
+[!endif]
+[!if WTL_ENABLE_AX]
+#include <atlhost.h>
+[!endif]
+#include <atlwin.h>
+[!if WTL_ENABLE_AX]
+#include <atlctl.h>
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+[!if WTL_USE_CMDBAR]
+#include <atlctrlw.h>
+[!endif]
+[!if WTL_APPTYPE_TABVIEW]
+#include <atlctrlx.h>
+[!endif]
+[!if WTL_APPTYPE_EXPLORER]
+#include <atlctrlx.h>
+#include <atlsplit.h>
+[!endif]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_SCROLL]
+#include <atlscrl.h>
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_USE_EMBEDDED_MANIFEST]
+
+#if defined _M_IX86
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+[!endif]
diff --git a/include/WTL/AppWiz/Files/Templates/1041/toolbar.bmp b/include/WTL/AppWiz/Files/Templates/1041/toolbar.bmp
new file mode 100644 (file)
index 0000000..60f7a16
Binary files /dev/null and b/include/WTL/AppWiz/Files/Templates/1041/toolbar.bmp differ
diff --git a/include/WTL/AppWiz/Files/WTLAppWiz.ico b/include/WTL/AppWiz/Files/WTLAppWiz.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/AppWiz/Files/WTLAppWiz.ico differ
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/AboutDlg.cpp b/include/WTL/AppWizCE/Files/Templates/1033/AboutDlg.cpp
new file mode 100644 (file)
index 0000000..c1f285a
--- /dev/null
@@ -0,0 +1,20 @@
+// aboutdlg.cpp : implementation of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "aboutdlg.h"
+
+LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CenterWindow(GetParent());
+       return TRUE;
+}
+
+LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       EndDialog(wID);
+       return 0;
+}
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/AboutDlg.h b/include/WTL/AppWizCE/Files/Templates/1033/AboutDlg.h
new file mode 100644 (file)
index 0000000..cca6b55
--- /dev/null
@@ -0,0 +1,42 @@
+// aboutdlg.h : interface of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CAboutDlg : public CDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTBOX };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+[!endif]
+};
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/Frame.cpp b/include/WTL/AppWizCE/Files/Templates/1033/Frame.cpp
new file mode 100644 (file)
index 0000000..e674190
--- /dev/null
@@ -0,0 +1,249 @@
+// [!output WTL_FRAME_FILE].cpp : implmentation of the [!output WTL_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "aboutdlg.h"
+[!if WTL_USE_VIEW]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+#include "[!output WTL_FRAME_FILE].h"
+
+BOOL [!output WTL_FRAME_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_USE_VIEW]
+       if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+               return TRUE;
+
+       return m_view.PreTranslateMessage(pMsg);
+[!else]
+       return [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+}
+
+BOOL [!output WTL_FRAME_CLASS]::OnIdle()
+{
+[!if WTL_USE_TOOLBAR]
+       UIUpdateToolBar();
+[!endif]
+       return FALSE;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+[!if WTL_USE_AYGSHELL]
+[!if !WTL_USE_SP03_COMPAT_MENUS]
+               CreateSimpleCEMenuBar(IDR_MAINFRAME);
+[!else]
+               CreateSimpleCEMenuBar();
+[!endif]
+[!else]
+               CreateSimpleCECommandBar(MAKEINTRESOURCE(IDR_MAINFRAME));
+[!endif]
+
+[!if WTL_USE_TOOLBAR]
+       CreateSimpleToolBar();
+[!endif]
+[!if WTL_USE_STATUSBAR]
+
+       CreateSimpleStatusBar();
+[!endif]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+
+       m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+       //TODO: Replace with a URL of your choice
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES]);
+[!else]
+
+       m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES]);
+[!endif]
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_USE_TOOLBAR]
+
+       UIAddToolBar(m_hWndToolBar);
+       UISetCheck(ID_VIEW_TOOLBAR, 1);
+[!endif]
+[!if WTL_USE_STATUSBAR]
+       UISetCheck(ID_VIEW_STATUS_BAR, 1);
+[!endif]
+
+       // register object for message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->AddMessageFilter(this);
+       pLoop->AddIdleHandler(this);
+
+       return 0;
+}
+
+[!if WTL_COM_SERVER]
+LRESULT [!output WTL_FRAME_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // unregister message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->RemoveMessageFilter(this);
+       pLoop->RemoveIdleHandler(this);
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+[!if WTL_APPTYPE_MTSDI]
+       ::PostQuitMessage(1);
+[!endif]
+       return 0;
+}
+
+[!endif]
+[!if WTL_USE_SP03_COMPAT_MENUS]
+LRESULT [!output WTL_FRAME_CLASS]::OnAction(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: add code
+
+       return 0;
+}
+
+[!endif]
+LRESULT [!output WTL_FRAME_CLASS]::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       PostMessage(WM_CLOSE);
+       return 0;
+}
+
+LRESULT [!output WTL_FRAME_CLASS]::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: add code to initialize document
+
+       return 0;
+}
+
+[!if WTL_APPTYPE_MTSDI]
+LRESULT [!output WTL_FRAME_CLASS]::OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
+       return 0;
+}
+
+[!endif]
+[!if WTL_USE_TOOLBAR]
+LRESULT [!output WTL_FRAME_CLASS]::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       BOOL bVisible = !::IsWindowVisible(m_hWndToolBar);
+       ::ShowWindow(m_hWndToolBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+       UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+       UpdateLayout();
+       return 0;
+}
+
+[!endif]
+[!if WTL_USE_STATUSBAR]
+LRESULT [!output WTL_FRAME_CLASS]::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+       ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+       UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+       UpdateLayout();
+       return 0;
+}
+
+[!endif]
+LRESULT [!output WTL_FRAME_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CAboutDlg dlg;
+       dlg.DoModal();
+       return 0;
+}
+[!if WTL_USE_SINGLE_APP_INSTANCE]
+
+HRESULT [!output WTL_FRAME_CLASS]::ActivatePreviousInstance(HINSTANCE hInstance)
+{
+       CFrameWndClassInfo& classInfo = [!output WTL_FRAME_CLASS]::GetWndClassInfo();
+       ATLVERIFY(::LoadString(hInstance, IDR_MAINFRAME, classInfo.m_szAutoName, sizeof(classInfo.m_szAutoName)/sizeof(classInfo.m_szAutoName[0])));
+       classInfo.m_wc.lpszClassName = classInfo.m_szAutoName;
+       const TCHAR* pszClass = classInfo.m_wc.lpszClassName;
+       if(pszClass == NULL || *pszClass == _T('\0'))
+       {
+               return E_FAIL;
+       }
+
+       // Orginally 500ms in SmartPhone 2003 App Wizard generated code
+       // A lower value will result in a more responsive start-up of 
+       // the existing instance or termination of this instance.
+       const DWORD dRetryInterval = 100; 
+
+       // Orginally 5 in SmartPhone 2003 App Wizard generated code
+       // Multiplied by 5, since wait time was divided by 5.
+       const int iMaxRetries = 25;
+
+       for(int i = 0; i < iMaxRetries; ++i)
+       {
+               // Don't need ownership of the mutex
+               HANDLE hMutex = CreateMutex(NULL, FALSE, pszClass);
+
+               DWORD dw = GetLastError();
+
+               if(hMutex == NULL)
+               {
+                       // ERROR_INVALID_HANDLE - A non-mutex object with this name already exists.
+                       HRESULT hr = (dw == ERROR_INVALID_HANDLE) ? E_INVALIDARG : E_FAIL;
+                       return hr;
+               }
+
+               // If the mutex already exists, then there should be another instance running
+               if(dw == ERROR_ALREADY_EXISTS)
+               {
+                       // Just needed the error result, in this case, so close the handle.
+                       CloseHandle(hMutex);
+
+                       // Try to find the other instance, don't need to close HWND's.
+                       // Don't check title in case it is changed by app after init.
+                       HWND hwnd = FindWindow(pszClass, NULL);
+
+                       if(hwnd == NULL)
+                       {
+                               // It's possible that the other istance is in the process of starting up or shutting down.
+                               // So wait a bit and try again.
+                               Sleep(dRetryInterval);
+                               continue;
+                       }
+                       else
+                       {
+                               // Set the previous instance as the foreground window
+
+                               // The "| 0x1" in the code below activates the correct owned window 
+                               // of the previous instance's main window according to the SmartPhone 2003
+                               // wizard generated code.
+                               if(SetForegroundWindow(reinterpret_cast<HWND>(reinterpret_cast<ULONG>(hwnd) | 0x1)) != 0)
+                               {
+                                       // S_FALSE indicates that another instance was activated, so this instance should terminate.
+                                       return S_FALSE;
+                               }
+                       }
+               }
+               else
+               {
+                       // This is the first istance, so return S_OK.
+                       // Don't close the mutext handle here.
+                       // Do it on app shutdown instead.
+                       return S_OK;
+               }
+       }
+
+       // The mutex was created by another instance, but it's window couldn't be brought
+       // to the foreground, so ssume  it's not a invalid instance (not this app, hung, etc.)
+       // and let this one start.
+       return S_OK;
+}
+[!endif]
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/Frame.h b/include/WTL/AppWizCE/Files/Templates/1033/Frame.h
new file mode 100644 (file)
index 0000000..72038c7
--- /dev/null
@@ -0,0 +1,341 @@
+// [!output WTL_FRAME_FILE].h : interface of the [!output WTL_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class [!output WTL_FRAME_CLASS] : public [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>, public CUpdateUI<[!output WTL_FRAME_CLASS]>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
+
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+       [!output WTL_VIEW_CLASS] m_view;
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_USE_VIEW]
+               if([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+[!else]
+               return [!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL OnIdle();
+[!else]
+       virtual BOOL OnIdle()
+       {
+[!if WTL_USE_TOOLBAR]
+               UIUpdateToolBar();
+[!endif]
+               return FALSE;
+       }
+[!endif]
+
+       BEGIN_UPDATE_UI_MAP([!output WTL_FRAME_CLASS])
+[!if WTL_USE_TOOLBAR && !WTL_USE_AYGSHELL]
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+[!endif]
+       END_UPDATE_UI_MAP()
+
+       BEGIN_MSG_MAP([!output WTL_FRAME_CLASS])
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+[!if WTL_COM_SERVER]
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+[!endif]
+[!if WTL_USE_SP03_COMPAT_MENUS]
+               COMMAND_ID_HANDLER(ID_ACTION, OnAction)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+[!if WTL_APPTYPE_MTSDI]
+               COMMAND_ID_HANDLER(ID_FILE_NEW_WINDOW, OnFileNewWindow)
+[!endif]
+[!if WTL_USE_TOOLBAR && !WTL_USE_AYGSHELL]
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               CHAIN_MSG_MAP(CUpdateUI<[!output WTL_FRAME_CLASS]>)
+               CHAIN_MSG_MAP([!output WTL_FRAME_BASE_CLASS]<[!output WTL_FRAME_CLASS]>)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_USE_AYGSHELL]
+[!if !WTL_USE_SP03_COMPAT_MENUS]
+               CreateSimpleCEMenuBar(IDR_MAINFRAME);
+[!else]
+               CreateSimpleCEMenuBar();
+[!endif]
+[!else]
+               CreateSimpleCECommandBar(MAKEINTRESOURCE(IDR_MAINFRAME));
+[!endif]
+[!if WTL_USE_TOOLBAR]
+               CreateSimpleToolBar();
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               CreateSimpleStatusBar();
+[!endif]
+[!if WTL_APPTYPE_SDI || WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+
+               m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+[!if WTL_VIEWTYPE_HTML]
+
+               //TODO: Replace with a URL of your choice
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("http://www.microsoft.com"), [!output WTL_VIEW_STYLES]);
+[!else]
+
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES]);
+[!endif]
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_USE_TOOLBAR]
+
+               UIAddToolBar(m_hWndToolBar);
+[!if !WTL_USE_AYGSHELL]
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+[!endif]
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+[!endif]
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               return 0;
+       }
+
+[!endif]
+[!if WTL_COM_SERVER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+[!if WTL_APPTYPE_MTSDI]
+               ::PostQuitMessage(1);
+[!endif]
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_SP03_COMPAT_MENUS]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAction(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnAction(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: add code
+
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: add code to initialize document
+
+               return 0;
+       }
+
+[!endif]
+[!if WTL_APPTYPE_MTSDI]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_TOOLBAR && !WTL_USE_AYGSHELL]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bVisible = !::IsWindowVisible(m_hWndToolBar);
+               ::ShowWindow(m_hWndToolBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_STATUSBAR]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+[!endif]
+[!if WTL_USE_SINGLE_APP_INSTANCE]
+
+[!if WTL_USE_CPP_FILES]
+       static HRESULT ActivatePreviousInstance(HINSTANCE hInstance);
+[!else]
+       static HRESULT ActivatePreviousInstance(HINSTANCE hInstance)
+       {
+               CFrameWndClassInfo& classInfo = [!output WTL_FRAME_CLASS]::GetWndClassInfo();
+               ATLVERIFY(::LoadString(hInstance, IDR_MAINFRAME, classInfo.m_szAutoName, sizeof(classInfo.m_szAutoName)/sizeof(classInfo.m_szAutoName[0])));
+               classInfo.m_wc.lpszClassName = classInfo.m_szAutoName;
+               const TCHAR* pszClass = classInfo.m_wc.lpszClassName;
+               if(pszClass == NULL || *pszClass == _T('\0'))
+               {
+                       return E_FAIL;
+               }
+
+               // Orginally 500ms in SmartPhone 2003 App Wizard generated code
+               // A lower value will result in a more responsive start-up of 
+               // the existing instance or termination of this instance.
+               const DWORD dRetryInterval = 100; 
+
+               // Orginally 5 in SmartPhone 2003 App Wizard generated code
+               // Multiplied by 5, since wait time was divided by 5.
+               const int iMaxRetries = 25;
+
+               for(int i = 0; i < iMaxRetries; ++i)
+               {
+                       // Don't need ownership of the mutex
+                       HANDLE hMutex = CreateMutex(NULL, FALSE, pszClass);
+
+                       DWORD dw = GetLastError();
+
+                       if(hMutex == NULL)
+                       {
+                               // ERROR_INVALID_HANDLE - A non-mutex object with this name already exists.
+                               HRESULT hr = (dw == ERROR_INVALID_HANDLE) ? E_INVALIDARG : E_FAIL;
+                               return hr;
+                       }
+
+                       // If the mutex already exists, then there should be another instance running
+                       if(dw == ERROR_ALREADY_EXISTS)
+                       {
+                               // Just needed the error result, in this case, so close the handle.
+                               CloseHandle(hMutex);
+
+                               // Try to find the other instance, don't need to close HWND's.
+                               // Don't check title in case it is changed by app after init.
+                               HWND hwnd = FindWindow(pszClass, NULL);
+
+                               if(hwnd == NULL)
+                               {
+                                       // It's possible that the other istance is in the process of starting up or shutting down.
+                                       // So wait a bit and try again.
+                                       Sleep(dRetryInterval);
+                                       continue;
+                               }
+                               else
+                               {
+                                       // Set the previous instance as the foreground window
+
+                                       // The "| 0x1" in the code below activates the correct owned window 
+                                       // of the previous instance's main window according to the SmartPhone 2003
+                                       // wizard generated code.
+                                       if(SetForegroundWindow(reinterpret_cast<HWND>(reinterpret_cast<ULONG>(hwnd) | 0x1)) != 0)
+                                       {
+                                               // S_FALSE indicates that another instance was activated, so this instance should terminate.
+                                               return S_FALSE;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               // This is the first istance, so return S_OK.
+                               // Don't close the mutext handle here.
+                               // Do it on app shutdown instead.
+                               return S_OK;
+                       }
+               }
+
+               // The mutex was created by another instance, but it's window couldn't be brought
+               // to the foreground, so ssume  it's not a invalid instance (not this app, hung, etc.)
+               // and let this one start.
+               return S_OK;
+       }
+[!endif]
+[!endif]
+};
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/MainDlg.cpp b/include/WTL/AppWizCE/Files/Templates/1033/MainDlg.cpp
new file mode 100644 (file)
index 0000000..f39e4d3
--- /dev/null
@@ -0,0 +1,165 @@
+// [!output WTL_MAINDLG_FILE].cpp : implementation of the [!output WTL_MAINDLG_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+#include "aboutdlg.h"
+[!endif]
+#include "[!output WTL_MAINDLG_FILE].h"
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+BOOL [!output WTL_MAINDLG_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_HOST_AX]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       HWND hWndCtl = ::GetFocus();
+       if(IsChild(hWndCtl))
+       {
+               // find a direct child of the dialog from the window that has focus
+               while(::GetParent(hWndCtl) != m_hWnd)
+                       hWndCtl = ::GetParent(hWndCtl);
+
+               // give control a chance to translate this message
+               if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                       return TRUE;
+       }
+
+[!endif]
+       return CWindow::IsDialogMessage(pMsg);
+}
+
+BOOL [!output WTL_MAINDLG_CLASS]::OnIdle()
+{
+       return FALSE;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // center the dialog on the screen
+       CenterWindow();
+
+       // set icons
+       HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+       SetIcon(hIcon, TRUE);
+       HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+       SetIcon(hIconSmall, FALSE);
+
+       // register object for message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->AddMessageFilter(this);
+       pLoop->AddIdleHandler(this);
+
+       UIAddChildWindowContainer(m_hWnd);
+
+       return TRUE;
+}
+
+[!if WTL_COM_SERVER]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // unregister message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->RemoveMessageFilter(this);
+       pLoop->RemoveIdleHandler(this);
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+       return 0;
+}
+
+[!endif]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CAboutDlg dlg;
+       dlg.DoModal();
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: Add validation code 
+       CloseDialog(wID);
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CloseDialog(wID);
+       return 0;
+}
+
+void [!output WTL_MAINDLG_CLASS]::CloseDialog(int nVal)
+{
+       DestroyWindow();
+       ::PostQuitMessage(nVal);
+}
+[!endif]
+[!if WTL_APPTYPE_DLG && WTL_APPTYPE_DLG_MODAL]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+
+[!endif]
+       // center the dialog on the screen
+       CenterWindow();
+
+       // set icons
+       HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+       SetIcon(hIcon, TRUE);
+       HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+               IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+       SetIcon(hIconSmall, FALSE);
+
+       return TRUE;
+}
+
+[!if WTL_COM_SERVER]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       // if UI is the last thread, no need to wait
+       if(_Module.GetLockCount() == 1)
+       {
+               _Module.m_dwTimeOut = 0L;
+               _Module.m_dwPause = 0L;
+       }
+       _Module.Unlock();
+       return 0;
+}
+
+[!endif]
+LRESULT [!output WTL_MAINDLG_CLASS]::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CSimpleDialog<IDD_ABOUTBOX, FALSE> dlg;
+       dlg.DoModal();
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: Add validation code 
+       EndDialog(wID);
+       return 0;
+}
+
+LRESULT [!output WTL_MAINDLG_CLASS]::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       EndDialog(wID);
+       return 0;
+}
+[!endif]
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/MainDlg.h b/include/WTL/AppWizCE/Files/Templates/1033/MainDlg.h
new file mode 100644 (file)
index 0000000..0d7402e
--- /dev/null
@@ -0,0 +1,258 @@
+// [!output WTL_MAINDLG_FILE].h : interface of the [!output WTL_MAINDLG_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+class [!output WTL_MAINDLG_CLASS] : public [!output WTL_MAINDLG_BASE_CLASS]<[!output WTL_MAINDLG_CLASS]>, public CUpdateUI<[!output WTL_MAINDLG_CLASS]>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       enum { IDD = IDD_MAINDLG };
+
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_HOST_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+[!endif]
+               return CWindow::IsDialogMessage(pMsg);
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       virtual BOOL OnIdle();
+[!else]
+       virtual BOOL OnIdle()
+       {
+               return FALSE;
+       }
+[!endif]
+
+       BEGIN_UPDATE_UI_MAP([!output WTL_MAINDLG_CLASS])
+       END_UPDATE_UI_MAP()
+
+       BEGIN_MSG_MAP([!output WTL_MAINDLG_CLASS])
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+[!if WTL_COM_SERVER]
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_ID_HANDLER(IDOK, OnOK)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // center the dialog on the screen
+               CenterWindow();
+
+               // set icons
+               HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+               SetIcon(hIcon, TRUE);
+               HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+               SetIcon(hIconSmall, FALSE);
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               UIAddChildWindowContainer(m_hWnd);
+
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_COM_SERVER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: Add validation code 
+               CloseDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CloseDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+       void CloseDialog(int nVal);
+[!else]
+       void CloseDialog(int nVal)
+       {
+               DestroyWindow();
+               ::PostQuitMessage(nVal);
+       }
+[!endif]
+};
+[!endif]
+[!if WTL_APPTYPE_DLG && WTL_APPTYPE_DLG_MODAL]
+class [!output WTL_MAINDLG_CLASS] : public [!output WTL_MAINDLG_BASE_CLASS]<[!output WTL_MAINDLG_CLASS]>
+{
+public:
+       enum { IDD = IDD_MAINDLG };
+
+       BEGIN_MSG_MAP([!output WTL_MAINDLG_CLASS])
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+[!if WTL_COM_SERVER]
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_ID_HANDLER(IDOK, OnOK)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+[!if WTL_COM_SERVER]
+               _Module.Lock();
+
+[!endif]
+               // center the dialog on the screen
+               CenterWindow();
+
+               // set icons
+               HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+               SetIcon(hIcon, TRUE);
+               HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+               SetIcon(hIconSmall, FALSE);
+
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_COM_SERVER]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // if UI is the last thread, no need to wait
+               if(_Module.GetLockCount() == 1)
+               {
+                       _Module.m_dwTimeOut = 0L;
+                       _Module.m_dwPause = 0L;
+               }
+               _Module.Unlock();
+               return 0;
+       }
+
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CSimpleDialog<IDD_ABOUTBOX, FALSE> dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: Add validation code 
+               EndDialog(wID);
+               return 0;
+       }
+
+[!endif]
+[!if WTL_USE_CPP_FILES]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+[!else]
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+[!endif]
+};
+[!endif]
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/View.cpp b/include/WTL/AppWizCE/Files/Templates/1033/View.cpp
new file mode 100644 (file)
index 0000000..d6a8f76
--- /dev/null
@@ -0,0 +1,56 @@
+// [!output WTL_VIEW_FILE].cpp : implementation of the [!output WTL_VIEW_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include "[!output WTL_VIEW_FILE].h"
+
+BOOL [!output WTL_VIEW_CLASS]::PreTranslateMessage(MSG* pMsg)
+{
+[!if WTL_HOST_AX]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       HWND hWndCtl = ::GetFocus();
+       if(IsChild(hWndCtl))
+       {
+               // find a direct child of the dialog from the window that has focus
+               while(::GetParent(hWndCtl) != m_hWnd)
+                       hWndCtl = ::GetParent(hWndCtl);
+
+               // give control a chance to translate this message
+               if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                       return TRUE;
+       }
+
+[!endif]
+[!if WTL_VIEWTYPE_HTML]
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       // give HTML page a chance to translate this message
+       return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+       return CWindow::IsDialogMessage(pMsg);
+[!else]
+       pMsg;
+       return FALSE;
+[!endif]
+[!endif]
+}
+[!if WTL_VIEWTYPE_GENERIC]
+
+LRESULT [!output WTL_VIEW_CLASS]::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CPaintDC dc(m_hWnd);
+
+       //TODO: Add your drawing code here
+
+       return 0;
+}
+[!endif]
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/View.h b/include/WTL/AppWizCE/Files/Templates/1033/View.h
new file mode 100644 (file)
index 0000000..e7576d9
--- /dev/null
@@ -0,0 +1,92 @@
+// [!output WTL_VIEW_FILE].h : interface of the [!output WTL_VIEW_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_VIEWTYPE_GENERIC || WTL_VIEWTYPE_FORM]
+class [!output WTL_VIEW_CLASS] : public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS]>
+[!else]
+class [!output WTL_VIEW_CLASS] : public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS], [!output WTL_VIEW_BASE]>
+[!endif]
+{
+public:
+[!if WTL_VIEWTYPE_GENERIC]
+       DECLARE_WND_CLASS(NULL)
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+       enum { IDD = IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM };
+[!else]
+       DECLARE_WND_SUPERCLASS(NULL, [!output WTL_VIEW_BASE]::GetWndClassName())
+[!endif]
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+       BOOL PreTranslateMessage(MSG* pMsg);
+[!else]
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_HOST_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+[!endif]
+[!if WTL_VIEWTYPE_HTML]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               // give HTML page a chance to translate this message
+               return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+               return CWindow::IsDialogMessage(pMsg);
+[!else]
+               pMsg;
+               return FALSE;
+[!endif]
+[!endif]
+       }
+[!endif]
+
+       BEGIN_MSG_MAP([!output WTL_VIEW_CLASS])
+[!if WTL_VIEWTYPE_GENERIC]
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+[!endif]
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+[!if WTL_VIEWTYPE_GENERIC]
+[!if WTL_USE_CPP_FILES]
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+[!else]
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CPaintDC dc(m_hWnd);
+
+               //TODO: Add your drawing code here
+
+               return 0;
+       }
+[!endif]
+[!endif]
+};
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/resource.h b/include/WTL/AppWizCE/Files/Templates/1033/resource.h
new file mode 100644 (file)
index 0000000..254d0dc
--- /dev/null
@@ -0,0 +1,47 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by [!output PROJECT_NAME].RC
+//
+
+[!if WTL_USE_SP03_COMPAT_MENUS]
+#define IDS_LVK_EXIT                           98
+#define IDS_RVK_MENU                           99
+[!endif]
+
+[!if WTL_COM_SERVER]
+#define IDS_PROJNAME                           100
+#define IDR_[!output UPPERCASE_SAFE_PROJECT_NAME]      100
+[!endif]
+
+#define IDD_ABOUTBOX                           100
+#define IDR_MAINFRAME                          128
+[!if WTL_APPTYPE_SDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 129
+[!endif]
+[!endif]
+[!else]
+[!if WTL_APPTYPE_DLG]
+#define IDD_MAINDLG                            129
+[!endif]
+[!endif]
+[!if WTL_APPTYPE_MTSDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 130
+[!endif]
+[!endif]
+#define ID_FILE_NEW_WINDOW                     32771
+[!endif]
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE       201
+#define _APS_NEXT_CONTROL_VALUE                1000
+#define _APS_NEXT_SYMED_VALUE          101
+#define _APS_NEXT_COMMAND_VALUE                32772
+#endif
+#endif
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/root.cpp b/include/WTL/AppWizCE/Files/Templates/1033/root.cpp
new file mode 100644 (file)
index 0000000..4375e1b
--- /dev/null
@@ -0,0 +1,355 @@
+// [!output PROJECT_NAME].cpp : main source file for [!output PROJECT_NAME].exe
+//
+
+#include "stdafx.h"
+[!if !WTL_USE_CPP_FILES]
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+[!endif]
+
+#include "resource.h"
+
+[!if WTL_COM_SERVER]
+// Note: Proxy/Stub Information
+//             To build a separate proxy/stub DLL, 
+//             run nmake -f [!output PROJECT_NAME]ps.mk in the project directory.
+#include "initguid.h"
+#include "[!output PROJECT_NAME].h"
+#include "[!output PROJECT_NAME]_i.c"
+
+[!endif]
+[!if WTL_USE_VIEW]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+[!if !WTL_APPTYPE_DLG_MODAL]
+#include "aboutdlg.h"
+[!endif]
+[!if WTL_APPTYPE_DLG]
+#include "[!output WTL_MAINDLG_FILE].h"
+[!else]
+#include "[!output WTL_FRAME_FILE].h"
+[!endif]
+[!if WTL_COM_SERVER]
+
+CServerAppModule _Module;
+
+BEGIN_OBJECT_MAP(ObjectMap)
+END_OBJECT_MAP()
+[!else]
+
+CAppModule _Module;
+[!endif]
+[!if WTL_APPTYPE_DLG && !WTL_APPTYPE_DLG_MODAL]
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWNORMAL)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       [!output WTL_MAINDLG_CLASS] dlgMain;
+
+       if(dlgMain.Create(NULL) == NULL)
+       {
+               ATLTRACE(_T("Main dialog creation failed!\n"));
+               return 0;
+       }
+
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+[!endif]
+       dlgMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+[!endif]
+[!if !WTL_APPTYPE_DLG && WTL_APPTYPE_MTSDI]
+
+class C[!output SAFE_PROJECT_NAME]ThreadManager
+{
+public:
+       // thread init param
+       struct _RunData
+       {
+               LPTSTR lpstrCmdLine;
+               int nCmdShow;
+       };
+
+       // thread proc
+       static DWORD WINAPI RunThread(LPVOID lpData)
+       {
+               CMessageLoop theLoop;
+               _Module.AddMessageLoop(&theLoop);
+
+               _RunData* pData = (_RunData*)lpData;
+               [!output WTL_FRAME_CLASS] wndFrame;
+
+               if(wndFrame.CreateEx() == NULL)
+               {
+                       ATLTRACE(_T("Frame window creation failed!\n"));
+                       return 0;
+               }
+
+[!if WTL_COM_SERVER]
+               _Module.Lock();
+[!endif]
+               wndFrame.ShowWindow(pData->nCmdShow);
+               ::SetForegroundWindow(wndFrame);        // Win95 needs this
+               delete pData;
+
+               int nRet = theLoop.Run();
+
+               _Module.RemoveMessageLoop();
+               return nRet;
+       }
+
+       DWORD m_dwCount;
+       HANDLE m_arrThreadHandles[MAXIMUM_WAIT_OBJECTS - 1];
+
+       C[!output SAFE_PROJECT_NAME]ThreadManager() : m_dwCount(0)
+       { }
+
+// Operations
+       DWORD AddThread(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               if(m_dwCount == (MAXIMUM_WAIT_OBJECTS - 1))
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create ANY MORE threads!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       return 0;
+               }
+
+               _RunData* pData = new _RunData;
+               pData->lpstrCmdLine = lpstrCmdLine;
+               pData->nCmdShow = nCmdShow;
+               DWORD dwThreadID;
+               HANDLE hThread = ::CreateThread(NULL, 0, RunThread, pData, 0, &dwThreadID);
+               if(hThread == NULL)
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create thread!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       return 0;
+               }
+
+               m_arrThreadHandles[m_dwCount] = hThread;
+               m_dwCount++;
+               return dwThreadID;
+       }
+
+       void RemoveThread(DWORD dwIndex)
+       {
+               ::CloseHandle(m_arrThreadHandles[dwIndex]);
+               if(dwIndex != (m_dwCount - 1))
+                       m_arrThreadHandles[dwIndex] = m_arrThreadHandles[m_dwCount - 1];
+               m_dwCount--;
+       }
+
+       int Run(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               MSG msg;
+               // force message queue to be created
+               ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+
+               AddThread(lpstrCmdLine, nCmdShow);
+
+               int nRet = m_dwCount;
+               DWORD dwRet;
+               while(m_dwCount > 0)
+               {
+                       dwRet = ::MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles, FALSE, INFINITE, QS_ALLINPUT);
+
+                       if(dwRet == 0xFFFFFFFF)
+                       {
+                               ::MessageBox(NULL, _T("ERROR: Wait for multiple objects failed!!!"), _T("[!output PROJECT_NAME]"), MB_OK);
+                       }
+                       else if(dwRet >= WAIT_OBJECT_0 && dwRet <= (WAIT_OBJECT_0 + m_dwCount - 1))
+                       {
+                               RemoveThread(dwRet - WAIT_OBJECT_0);
+                       }
+                       else if(dwRet == (WAIT_OBJECT_0 + m_dwCount))
+                       {
+                               if(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+                               {
+                                       if(msg.message == WM_USER)
+                                               AddThread(_T(""), SW_SHOWNORMAL);
+                               }
+                       }
+                       else
+                       {
+                               ::MessageBeep((UINT)-1);
+                       }
+               }
+
+               return nRet;
+       }
+};
+[!endif]
+[!if !WTL_APPTYPE_DLG && !WTL_APPTYPE_MTSDI]
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWNORMAL)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       [!output WTL_FRAME_CLASS] wndMain;
+
+       if(wndMain.CreateEx() == NULL)
+       {
+               ATLTRACE(_T("Main window creation failed!\n"));
+               return 0;
+       }
+
+[!if WTL_COM_SERVER]
+       _Module.Lock();
+[!endif]
+       wndMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+[!endif]
+
+[!if !WTL_APPTYPE_DLG_MODAL]
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+[!else]
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)
+[!endif]
+{
+[!if WTL_USE_SINGLE_APP_INSTANCE]
+       HRESULT hRes = [!output WTL_FRAME_CLASS]::ActivatePreviousInstance(hInstance);
+       if(FAILED(hRes) || S_FALSE == hRes)
+       {
+               return hRes;
+       }
+
+       hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+[!else]
+       HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+[!endif]
+       ATLASSERT(SUCCEEDED(hRes));
+
+       // Calling AtlInitCommonControls is not necessary to utilize picture,
+       // static text, edit box, group box, button, check box, radio button, 
+       // combo box, list box, or the horizontal and vertical scroll bars.
+       // Calling AtlInitCommonControls with 0 is required to utilize the spin, 
+       // progress, slider, list, tree, and tab controls.
+       // Adding the ICC_DATE_CLASSES flag is required to initialize the 
+       // date time picker and month calendar controls.
+       // Add additional flags to support additoinal controls not mentioned above.
+       AtlInitCommonControls(ICC_DATE_CLASSES);
+[!if WTL_COM_SERVER]
+
+       hRes = _Module.Init(ObjectMap, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+[!else]
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+[!endif]
+[!if WTL_ENABLE_AX]
+       AtlAxWinInit();
+
+[!endif]
+[!if WTL_COM_SERVER]
+       // Parse command line, register or unregister or run the server
+       int nRet = 0;
+       TCHAR szTokens[] = _T("-/");
+       bool bRun = true;
+       bool bAutomation = false;
+
+       LPCTSTR lpszToken = _Module.FindOneOf(::GetCommandLine(), szTokens);
+       while(lpszToken != NULL)
+       {
+               if(lstrcmpi(lpszToken, _T("UnregServer")) == 0)
+               {
+                       _Module.UpdateRegistryFromResource(IDR_[!output UPPERCASE_SAFE_PROJECT_NAME], FALSE);
+                       nRet = _Module.UnregisterServer(TRUE);
+                       bRun = false;
+                       break;
+               }
+               else if(lstrcmpi(lpszToken, _T("RegServer")) == 0)
+               {
+                       _Module.UpdateRegistryFromResource(IDR_[!output UPPERCASE_SAFE_PROJECT_NAME], TRUE);
+                       nRet = _Module.RegisterServer(TRUE);
+                       bRun = false;
+                       break;
+               }
+               else if((lstrcmpi(lpszToken, _T("Automation")) == 0) ||
+                       (lstrcmpi(lpszToken, _T("Embedding")) == 0))
+               {
+                       bAutomation = true;
+                       break;
+               }
+               lpszToken = _Module.FindOneOf(lpszToken, szTokens);
+       }
+
+       if(bRun)
+       {
+               _Module.StartMonitor();
+               hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
+               ATLASSERT(SUCCEEDED(hRes));
+               hRes = ::CoResumeClassObjects();
+               ATLASSERT(SUCCEEDED(hRes));
+
+               if(bAutomation)
+               {
+                       CMessageLoop theLoop;
+                       nRet = theLoop.Run();
+               }
+               else
+[!if WTL_APPTYPE_DLG_MODAL]
+               {
+                       [!output WTL_MAINDLG_CLASS] dlgMain;
+                       nRet = dlgMain.DoModal();
+               }
+[!else]
+[!if WTL_APPTYPE_MTSDI]
+               {
+                       C[!output SAFE_PROJECT_NAME]ThreadManager mgr;
+                       nRet = mgr.Run(lpstrCmdLine, nCmdShow);
+               }
+[!else]
+               {
+                       nRet = Run(lpstrCmdLine, nCmdShow);
+               }
+[!endif]
+[!endif]
+
+               _Module.RevokeClassObjects();
+               ::Sleep(_Module.m_dwPause);
+       }
+[!else]
+[!if WTL_APPTYPE_DLG_MODAL]
+       int nRet = 0;
+       // BLOCK: Run application
+       {
+               [!output WTL_MAINDLG_CLASS] dlgMain;
+               nRet = dlgMain.DoModal();
+       }
+[!else]
+[!if WTL_APPTYPE_MTSDI]
+       int nRet = 0;
+       // BLOCK: Run application
+       {
+               C[!output SAFE_PROJECT_NAME]ThreadManager mgr;
+               nRet = mgr.Run(lpstrCmdLine, nCmdShow);
+       }
+[!else]
+       int nRet = Run(lpstrCmdLine, nCmdShow);
+[!endif]
+[!endif]
+[!endif]
+[!if WTL_USE_VIEW]
+[!endif]
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/root.h b/include/WTL/AppWizCE/Files/Templates/1033/root.h
new file mode 100644 (file)
index 0000000..0c8afa9
--- /dev/null
@@ -0,0 +1 @@
+// [!output PROJECT_NAME].h
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/root.ico b/include/WTL/AppWizCE/Files/Templates/1033/root.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/AppWizCE/Files/Templates/1033/root.ico differ
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/rootidl.h b/include/WTL/AppWizCE/Files/Templates/1033/rootidl.h
new file mode 100644 (file)
index 0000000..fc5506c
--- /dev/null
@@ -0,0 +1,4 @@
+// [!output PROJECT_NAME].idl : IDL source for [!output PROJECT_NAME].exe
+//
+
+// Add interface and coclass declarations in this file
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/stdafx.cpp b/include/WTL/AppWizCE/Files/Templates/1033/stdafx.cpp
new file mode 100644 (file)
index 0000000..ef06d36
--- /dev/null
@@ -0,0 +1,20 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     [!output PROJECT_NAME].pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+[!if WTL_ENABLE_AX]
+
+#if (_ATL_VER < 0x0700)
+#include <wceatl.cpp>
+#endif //(_ATL_VER < 0x0700)
+[!endif]
+[!if WTL_COM_SERVER]
+
+#ifdef _ATL_STATIC_REGISTRY
+#include <statreg.h>
+#if (_ATL_VER < 0x0700)
+#include <statreg.cpp>
+#endif //(_ATL_VER < 0x0700)
+#endif //_ATL_STATIC_REGISTRY
+[!endif]
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/stdafx.h b/include/WTL/AppWizCE/Files/Templates/1033/stdafx.h
new file mode 100644 (file)
index 0000000..c119031
--- /dev/null
@@ -0,0 +1,59 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#pragma once
+
+[!if WTL_COM_SERVER]
+// The WTL App Wizard was instructed to create this project as a COM Server.
+// On Windows CE, COM Servers are only available on platforms that include DCOM.
+// Pocket PC 2000, 2002, 2003 and SmarthPhone 2002, 2003 do not include DCOM.
+// The Standard SDK for Windows CE versions 3.0, 4.0, 4.1, and 4.2 do not include DCOM.
+// For Windows CE OSes released after 2003, please see the associated docs.
+
+[!endif]
+// Change this value to use different versions
+#define WINVER 0x0420
+
+[!if WTL_USE_AYGSHELL]
+#define _WIN32_WCE_AYGSHELL 1
+
+[!endif]
+#include <atlbase.h>
+#include <atlapp.h>
+
+[!if WTL_COM_SERVER]
+extern CServerAppModule _Module;
+
+// This is here only to tell VC7 Class Wizard this is an ATL project
+#ifdef ___VC7_CLWIZ_ONLY___
+CComModule
+CExeModule
+#endif
+
+[!else]
+extern CAppModule _Module;
+
+[!endif]
+[!if WTL_ENABLE_AX || WTL_COM_SERVER]
+#include <atlcom.h>
+[!endif]
+[!if WTL_ENABLE_AX]
+#include <atlhost.h>
+[!endif]
+#include <atlwin.h>
+[!if WTL_ENABLE_AX]
+#include <atlctl.h>
+[!endif]
+[!if WTL_USE_CPP_FILES]
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+[!endif]
+[!if WTL_USE_AYGSHELL]
+
+#include <aygshell.h>
+#pragma comment(lib, "aygshell.lib")
+[!endif]
diff --git a/include/WTL/AppWizCE/Files/Templates/1033/toolbar.bmp b/include/WTL/AppWizCE/Files/Templates/1033/toolbar.bmp
new file mode 100644 (file)
index 0000000..1057142
Binary files /dev/null and b/include/WTL/AppWizCE/Files/Templates/1033/toolbar.bmp differ
diff --git a/include/WTL/AppWizCE/Files/WTLAppWizCE.ico b/include/WTL/AppWizCE/Files/WTLAppWizCE.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/AppWizCE/Files/WTLAppWizCE.ico differ
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/AboutDlg.cpp b/include/WTL/AppWizMobile/Files/Templates/1033/AboutDlg.cpp
new file mode 100644 (file)
index 0000000..d9b0ab0
--- /dev/null
@@ -0,0 +1,12 @@
+// AboutDlg.cpp : implementation of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+//?ppc
+#include "resourceppc.h"
+//?sp
+#include "resourcesp.h"
+//?end
+#include "aboutdlg.h"
+
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/AboutDlg.h b/include/WTL/AppWizMobile/Files/Templates/1033/AboutDlg.h
new file mode 100644 (file)
index 0000000..11444d4
--- /dev/null
@@ -0,0 +1,30 @@
+// aboutdlg.h : interface of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CAboutDlg : public CStdDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTBOX };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               CHAIN_MSG_MAP(CStdDialogImpl<CAboutDlg>)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+//?ppc
+               AtlCreateEmptyMenuBar(m_hWnd);
+//?end
+
+               return bHandled = FALSE;
+       }
+};
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/Frame.cpp b/include/WTL/AppWizMobile/Files/Templates/1033/Frame.cpp
new file mode 100644 (file)
index 0000000..27b3a04
--- /dev/null
@@ -0,0 +1,17 @@
+// [!output WTL_APPWND_FILE].cpp : implementation of the [!output WTL_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+//?ppc
+#include "resourceppc.h"
+//?sp
+#include "resourcesp.h"
+//?end
+
+#include "aboutdlg.h"
+[!if WTL_USE_VIEW_CLASS]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+#include "[!output WTL_APPWND_FILE].h"
+
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/Frame.h b/include/WTL/AppWizMobile/Files/Templates/1033/Frame.h
new file mode 100644 (file)
index 0000000..0644c06
--- /dev/null
@@ -0,0 +1,276 @@
+// [!output WTL_APPWND_FILE].h : interface of the [!output WTL_FRAME_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class [!output WTL_FRAME_CLASS] : 
+       public CFrameWindowImpl<[!output WTL_FRAME_CLASS]>, 
+       public CUpdateUI<[!output WTL_FRAME_CLASS]>,
+       public CAppWindow<[!output WTL_FRAME_CLASS]>,
+[!if WTL_FULLSCREEN]
+       public CFullScreenFrame<[!output WTL_FRAME_CLASS]>,
+[!endif]
+       public CMessageFilter, public CIdleHandler
+{
+public:
+       DECLARE_APP_FRAME_CLASS(NULL, IDR_MAINFRAME, L"Software\\WTL\\[!output NICE_SAFE_PROJECT_NAME]")
+
+[!if WTL_APPTYPE_SDI]
+[!if WTL_USE_VIEW]
+       [!output WTL_VIEW_CLASS] m_view;
+
+[!endif]
+[!endif]
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_USE_VIEW_CLASS || WTL_VIEWTYPE_AX]
+               if(CFrameWindowImpl<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg))
+                       return TRUE; 
+
+[!if !WTL_USE_VIEW_CLASS && WTL_VIEWTYPE_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+               return FALSE;
+[!else]
+               return m_view.IsWindow() ? m_view.PreTranslateMessage(pMsg) : FALSE;
+[!endif]
+[!else]
+               return CFrameWindowImpl<[!output WTL_FRAME_CLASS]>::PreTranslateMessage(pMsg);
+[!endif]
+       }
+
+// CAppWindow operations
+       bool AppHibernate( bool bHibernate)
+       {
+               // Insert your code here or delete member if not relevant
+               return bHibernate;
+       }
+
+       bool AppNewInstance( LPCTSTR lpstrCmdLine)
+       {
+               // Insert your code here or delete member if not relevant
+               return false;
+       }
+
+       void AppSave()
+       {
+               CAppInfo info;
+[!if WTL_FULLSCREEN]
+               info.Save( m_bFullScreen, L"Full");
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               bool bStatus = (UIGetState(ID_VIEW_STATUS_BAR) & UPDUI_CHECKED) == UPDUI_CHECKED;
+               info.Save(bStatus, L"Status");
+[!endif]
+               // Insert your code here
+       }
+
+//?sp
+       void AppBackKey() 
+       {
+               ::SHNavigateBack();
+       }
+//?end
+
+       virtual BOOL OnIdle()
+       {
+[!if WTL_USE_VIEW && WTL_VIEWTYPE_PROPSHEET]
+               if (!m_view.IsWindow() || m_view.SendMessage(PSM_GETCURRENTPAGEHWND) == NULL)
+                       PostMessage(WM_CLOSE);
+
+[!endif]
+               UIUpdateToolBar();
+[!if WTL_USE_STATUSBAR]
+               UIUpdateStatusBar();
+[!endif]
+               return FALSE;
+       }
+
+       BEGIN_UPDATE_UI_MAP([!output WTL_FRAME_CLASS])
+[!if WTL_FULLSCREEN]
+               UPDATE_ELEMENT(ID_VIEW_FULLSCREEN, UPDUI_MENUPOPUP)
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+[!endif]
+       END_UPDATE_UI_MAP()
+
+       BEGIN_MSG_MAP([!output WTL_FRAME_CLASS])
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+[!if SMARTPHONE2003_UI_MODEL || !WTL_MENU_TYPE_2003]
+               COMMAND_ID_HANDLER(ID_ACTION, OnAction)
+[!endif]
+[!if WTL_FULLSCREEN]
+               COMMAND_ID_HANDLER(ID_VIEW_FULLSCREEN, OnFullScreen)
+[!endif]
+[!if WTL_USE_STATUSBAR]
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               CHAIN_MSG_MAP(CAppWindow<[!output WTL_FRAME_CLASS]>)
+[!if WTL_FULLSCREEN]
+               CHAIN_MSG_MAP(CFullScreenFrame<[!output WTL_FRAME_CLASS]>)
+[!endif]
+               CHAIN_MSG_MAP(CUpdateUI<[!output WTL_FRAME_CLASS]>)
+               CHAIN_MSG_MAP(CFrameWindowImpl<[!output WTL_FRAME_CLASS]>)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CAppInfo info;
+[!if WTL_FULLSCREEN]
+
+               // Full screen mode delayed restoration 
+               bool bFull = false;
+               info.Restore(bFull, L"Full");
+               if (bFull)
+                       PostMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
+[!endif]
+
+[!if POCKETPC2003_UI_MODEL && SMARTPHONE2003_UI_MODEL && !WTL_MENU_TYPE_2005]
+#ifdef WIN32_PLATFORM_PSPC // PPC
+[!endif]
+[!if POCKETPC2003_UI_MODEL]
+[!if WTL_MENU_TYPE_BOTH]
+               OSVERSIONINFO osvi;
+               GetVersionEx(&osvi);
+               if (osvi.dwMajorVersion >= 5)
+                       CreateSimpleCEMenuBar();
+               else
+                       CreateSimpleCEMenuBar(IDR_MAINFRAME, 0, IDR_MAINFRAME, 7);
+[!endif]
+[!if WTL_MENU_TYPE_2003]
+               CreateSimpleCEMenuBar(IDR_MAINFRAME, 0, IDR_MAINFRAME, 7);
+[!endif]
+[!endif]
+[!if WTL_MENU_TYPE_2005]
+               CreateSimpleCEMenuBar();
+[!endif]
+[!if POCKETPC2003_UI_MODEL && SMARTPHONE2003_UI_MODEL]
+[!if WTL_MENU_TYPE_2005]
+#ifdef WIN32_PLATFORM_WFSP // SmartPhone
+[!else]
+#else // SmartPhone
+[!endif]
+[!endif]
+[!if SMARTPHONE2003_UI_MODEL]
+[!if !WTL_MENU_TYPE_2005]
+               CreateSimpleCEMenuBar();
+[!endif]
+               AtlActivateBackKey(m_hWndCECommandBar);
+[!endif]
+[!if POCKETPC2003_UI_MODEL && SMARTPHONE2003_UI_MODEL]
+#endif 
+[!endif]
+               UIAddToolBar(m_hWndCECommandBar);
+[!if WTL_USE_STATUSBAR]
+
+               // StatusBar state restoration 
+               bool bVisible = true;
+               info.Restore(bVisible, L"Status");
+               DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+               if (bVisible)
+                       dwStyle |= WS_VISIBLE;
+               // StatusBar creation 
+               CreateSimpleStatusBar(ATL_IDS_IDLEMESSAGE, dwStyle);
+               UIAddStatusBar(m_hWndStatusBar);
+               UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+[!endif]
+[!if WTL_USE_VIEW]
+
+[!if WTL_VIEWTYPE_AX]
+               //TODO: Replace with a ProgID of your choice
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, _T("WMPlayer.OCX"), [!output WTL_VIEW_STYLES]);
+[!else]
+[!if WTL_VIEWTYPE_FORM || WTL_VIEWTYPE_PROPSHEET]
+               m_hWndClient = m_view.Create(m_hWnd);
+[!else]
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, [!output WTL_VIEW_STYLES]);
+[!endif]
+[!endif]
+[!endif]
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               return 0;
+       }
+
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: add code to initialize document
+
+               return 0;
+       }
+
+[!if SMARTPHONE2003_UI_MODEL || !WTL_MENU_TYPE_2003]
+       LRESULT OnAction(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: add code
+
+               return 0;
+       }
+
+[!endif]
+[!if WTL_FULLSCREEN]
+       LRESULT OnFullScreen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               SetFullScreen( !m_bFullScreen );
+               UISetCheck( ID_VIEW_FULLSCREEN, m_bFullScreen);
+               return TRUE;
+       }
+
+[!endif]
+[!if WTL_USE_STATUSBAR]
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+
+[!endif]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+[!if WTL_FULLSCREEN]
+               FSDoModal(dlg);
+[!else]
+               dlg.DoModal();
+[!endif]
+               return 0;
+       }
+};
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/MainDlg.cpp b/include/WTL/AppWizMobile/Files/Templates/1033/MainDlg.cpp
new file mode 100644 (file)
index 0000000..0d176f0
--- /dev/null
@@ -0,0 +1,16 @@
+// [!output WTL_APPWND_FILE].cpp : implementation of the [!output WTL_MAINDLG_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+//?ppc
+#include "resourceppc.h"
+//?sp
+#include "resourcesp.h"
+//?end
+
+[!if WTL_APPTYPE_DLG]
+#include "aboutdlg.h"
+[!endif]
+#include "[!output WTL_APPWND_FILE].h"
+
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/MainDlg.h b/include/WTL/AppWizMobile/Files/Templates/1033/MainDlg.h
new file mode 100644 (file)
index 0000000..177a201
--- /dev/null
@@ -0,0 +1,135 @@
+// [!output WTL_APPWND_FILE].h : interface of the [!output WTL_MAINDLG_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class [!output WTL_MAINDLG_CLASS] : 
+       public [!output WTL_MAINDLG_BASE_CLASS]<[!output WTL_MAINDLG_CLASS]>,
+       public CUpdateUI<[!output WTL_MAINDLG_CLASS]>,
+       public CMessageFilter, public CIdleHandler
+{
+public:
+       DECLARE_APP_DLG_CLASS(NULL, IDR_MAINFRAME, L"Software\\WTL\\[!output NICE_SAFE_PROJECT_NAME]")
+
+[!if WTL_APP_DLG_ORIENT]
+       enum { IDD = IDD_MAINDLG, IDD_LANDSCAPE = IDD_MAINDLG_L };
+[!else]
+       enum { IDD = IDD_MAINDLG };
+[!endif]
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_ENABLE_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+[!endif]
+               return CWindow::IsDialogMessage(pMsg);
+       }
+
+// CAppWindow operations
+       bool AppHibernate( bool bHibernate)
+       {
+               // Insert your code here or delete member if not relevant
+               return bHibernate;
+       }
+
+       bool AppNewInstance( LPCTSTR lpstrCmdLine)
+       {
+               // Insert your code here or delete member if not relevant
+               return false;
+       }
+
+       void AppSave()
+       {
+               CAppInfo info;
+               // Insert your code here or delete member if not relevant
+       }
+
+//?sp
+       void AppBackKey() 
+       {
+               StdCloseDialog(IDCANCEL);
+       }
+//?end
+
+       virtual BOOL OnIdle()
+       {
+               return FALSE;
+       }
+
+       BEGIN_UPDATE_UI_MAP([!output WTL_MAINDLG_CLASS])
+       END_UPDATE_UI_MAP()
+
+[!if WTL_APP_DLG_RESIZE]
+       BEGIN_DLGRESIZE_MAP([!output WTL_MAINDLG_CLASS])
+               DLGRESIZE_CONTROL(IDC_INFOSTATIC, DLSZ_SIZE_X | DLSZ_SIZE_Y)
+               DLGRESIZE_CONTROL(ID_APP_ABOUT, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+       END_DLGRESIZE_MAP()
+[!endif]
+
+       BEGIN_MSG_MAP([!output WTL_MAINDLG_CLASS])
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+[!if WTL_APP_DLG_RESIZE]
+//?ppc
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+//?end
+[!endif]
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               CHAIN_MSG_MAP([!output WTL_MAINDLG_BASE_CLASS]<[!output WTL_MAINDLG_CLASS]>)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+
+               HWND hMenuBar = CreateMenuBar(ATL_IDM_MENU_DONECANCEL);
+               UIAddToolBar(hMenuBar);
+               UIAddChildWindowContainer(m_hWnd);
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               return bHandled = FALSE;
+       }
+
+[!if WTL_APP_DLG_RESIZE]
+//?ppc
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // prevent resizing on SIP change
+               return 0;
+       }
+//?end
+
+[!endif]
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+};
+
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/View.cpp b/include/WTL/AppWizMobile/Files/Templates/1033/View.cpp
new file mode 100644 (file)
index 0000000..c5e5b61
--- /dev/null
@@ -0,0 +1,13 @@
+// [!output WTL_VIEW_FILE].cpp : implementation of the [!output WTL_VIEW_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+//?ppc
+#include "resourceppc.h"
+//?sp
+#include "resourcesp.h"
+//?end
+
+#include "[!output WTL_VIEW_FILE].h"
+
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/View.h b/include/WTL/AppWizMobile/Files/Templates/1033/View.h
new file mode 100644 (file)
index 0000000..abbc471
--- /dev/null
@@ -0,0 +1,112 @@
+// [!output WTL_VIEW_FILE].h : interface of the [!output WTL_VIEW_CLASS] class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+[!if WTL_VIEWTYPE_GENERIC || WTL_VIEWTYPE_FORM || WTL_VIEWTYPE_PROPSHEET]
+class [!output WTL_VIEW_CLASS] : 
+[!if WTL_VIEW_SCROLL]
+       public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS]>, 
+       public [!output WTL_SCROLL_CLASS]<[!output WTL_VIEW_CLASS]>
+[!else]
+       public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS]>
+[!endif]
+[!else]
+class [!output WTL_VIEW_CLASS] : 
+       public [!output WTL_VIEW_BASE_CLASS]<[!output WTL_VIEW_CLASS], [!output WTL_VIEW_BASE]>
+[!endif]
+{
+public:
+[!if WTL_VIEWTYPE_GENERIC || WTL_VIEWTYPE_PROPSHEET]
+       DECLARE_WND_CLASS(NULL)
+[!else]
+[!if WTL_VIEWTYPE_FORM]
+       enum { IDD = IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM };
+[!else]
+       DECLARE_WND_SUPERCLASS(NULL, [!output WTL_VIEW_BASE]::GetWndClassName())
+[!endif]
+[!endif]
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+[!if WTL_HOST_AX]
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               HWND hWndCtl = ::GetFocus();
+               if(IsChild(hWndCtl))
+               {
+                       // find a direct child of the dialog from the window that has focus
+                       while(::GetParent(hWndCtl) != m_hWnd)
+                               hWndCtl = ::GetParent(hWndCtl);
+
+                       // give control a chance to translate this message
+                       if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                               return TRUE;
+               }
+
+[!endif]
+[!if WTL_VIEWTYPE_FORM || WTL_VIEWTYPE_PROPSHEET]
+               return IsDialogMessage(pMsg);
+[!else]
+[!if !WTL_HOST_AX]
+               pMsg;
+[!endif]
+               return FALSE;
+[!endif]
+       }
+[!if WTL_VIEW_SCROLL]
+
+       void DoPaint(CDCHandle dc)
+       {
+               //TODO: Add your drawing code here
+
+       }
+[!endif]
+[!if WTL_VIEWTYPE_PROPSHEET]
+
+public:
+       CPropertyPage<IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_PAGE> m_Page1, m_Page2;
+
+       [!output WTL_VIEW_CLASS]()
+       {
+               SetTitle(_T("Properties"));
+               SetLinkText(_T("Tap <file:\\Windows\\default.htm{here}>."));
+               m_Page1.SetTitle(_T("Page 1"));
+               AddPage(m_Page1);
+               m_Page2.SetTitle(_T("Page 2"));
+               AddPage(m_Page2);
+       }
+
+[!else]
+
+       BEGIN_MSG_MAP([!output WTL_VIEW_CLASS])
+[!if WTL_VIEWTYPE_GENERIC]
+[!if WTL_VIEW_SCROLL]
+               CHAIN_MSG_MAP([!output WTL_SCROLL_CLASS]<[!output WTL_VIEW_CLASS]>)
+[!else]
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+[!endif]
+[!endif]
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+[!if WTL_VIEWTYPE_GENERIC && !WTL_VIEW_SCROLL]
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CPaintDC dc(m_hWnd);
+
+               //TODO: Add your drawing code here
+
+               return 0;
+       }
+[!endif]
+[!endif]
+};
+
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/resource.h b/include/WTL/AppWizMobile/Files/Templates/1033/resource.h
new file mode 100644 (file)
index 0000000..0c72ec8
--- /dev/null
@@ -0,0 +1,39 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+//?ppc
+// Used by [!output PROJECT_NAME]ppc.RC
+//?sp
+// Used by [!output PROJECT_NAME]sp.RC
+//?end
+//
+
+#define IDD_ABOUTBOX                           100
+#define IDR_MAINFRAME                          128
+[!if WTL_APPTYPE_SDI]
+[!if WTL_USE_VIEW]
+[!if WTL_VIEWTYPE_FORM]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_FORM 129
+[!endif]
+[!if WTL_VIEWTYPE_PROPSHEET]
+#define IDD_[!output UPPERCASE_SAFE_PROJECT_NAME]_PAGE 129
+[!endif]
+[!endif]
+[!else]
+[!if WTL_APPTYPE_DLG]
+#define IDD_MAINDLG                            129
+[!if WTL_APP_DLG_ORIENT]
+#define IDD_MAINDLG_L                  130
+[!endif]
+[!endif]
+[!endif]
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE       201
+#define _APS_NEXT_CONTROL_VALUE                1000
+#define _APS_NEXT_SYMED_VALUE          101
+#define _APS_NEXT_COMMAND_VALUE                32772
+#endif
+#endif
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/root.cpp b/include/WTL/AppWizMobile/Files/Templates/1033/root.cpp
new file mode 100644 (file)
index 0000000..b7ca16e
--- /dev/null
@@ -0,0 +1,86 @@
+// [!output PROJECT_NAME].cpp : main source file for [!output PROJECT_NAME].exe
+//
+
+#include "stdafx.h"
+[!if !WTL_USE_CPP_FILES]
+
+#include <atlframe.h>
+#include <atlctrls.h>
+[!if WTL_USE_VIEW && WTL_VIEWTYPE_PROPSHEET]
+#define _WTL_NEW_PAGE_NOTIFY_HANDLERS
+#include <atldlgs.h>
+[!endif]
+[!if WTL_USE_STRING && !WTL_STRING_ATL]
+#include <atlmisc.h>
+[!endif]
+[!if WTL_VIEW_SCROLL || WTL_VIEW_ZOOM]
+[!if !WTL_USE_STRING || WTL_STRING_ATL]
+#include <atlmisc.h>
+[!endif]
+#include <atlscrl.h>
+[!else]
+#define _WTL_CE_NO_ZOOMSCROLL
+[!endif]
+[!if !WTL_FULLSCREEN]
+#define _WTL_CE_NO_FULLSCREEN
+[!endif]
+#include <atlwince.h>
+[!endif]
+
+//?ppc
+#include "resourceppc.h"
+//?sp
+#include "resourcesp.h"
+//?end
+
+[!if WTL_APPTYPE_SDI && WTL_USE_VIEW_CLASS]
+#include "[!output WTL_VIEW_FILE].h"
+[!endif]
+#include "AboutDlg.h"
+#include "[!output WTL_APPWND_FILE].h"
+
+CAppModule _Module;
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+       HRESULT hRes = [!output WTL_APPWND_CLASS]::ActivatePreviousInstance(hInstance, lpstrCmdLine);
+
+       if(FAILED(hRes) || S_FALSE == hRes)
+       {
+               return hRes;
+       }
+
+       hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       AtlInitCommonControls(ICC_DATE_CLASSES);
+       SHInitExtraControls();
+[!if WTL_VIEWTYPE_HTML]
+       InitHTMLControl(hInstance);
+[!endif]
+[!if WTL_VIEWTYPE_INKX]
+       InitInkX();
+[!endif]
+[!if WTL_VIEWTYPE_RICHINK]
+       InitRichInkDLL();
+[!endif]
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+[!if WTL_ENABLE_AX]
+       AtlAxWinInit();
+
+[!endif]
+       int nRet = [!output WTL_APPWND_CLASS]::AppRun(lpstrCmdLine, nCmdShow);
+
+[!if WTL_ENABLE_AX]
+       AtlAxWinTerm();
+
+[!endif]
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
+
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/root.ico b/include/WTL/AppWizMobile/Files/Templates/1033/root.ico
new file mode 100644 (file)
index 0000000..3bf85d3
Binary files /dev/null and b/include/WTL/AppWizMobile/Files/Templates/1033/root.ico differ
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/stdafx.cpp b/include/WTL/AppWizMobile/Files/Templates/1033/stdafx.cpp
new file mode 100644 (file)
index 0000000..8a08152
--- /dev/null
@@ -0,0 +1,11 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     [!output PROJECT_NAME].pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+[!if WTL_ENABLE_AX && WTL_EVC_COMPAT]
+
+#if (_ATL_VER < 0x0700)
+#include <wceatl.cpp>
+#endif //(_ATL_VER < 0x0700)
+[!endif]
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/stdafx.h b/include/WTL/AppWizMobile/Files/Templates/1033/stdafx.h
new file mode 100644 (file)
index 0000000..4f21b20
--- /dev/null
@@ -0,0 +1,77 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#pragma once
+
+// Change this value to use different versions
+#define WINVER 0x0420
+[!if WTL_ENABLE_AX]
+#define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA
+[!endif]
+#include <atlbase.h>
+#if _ATL_VER == 0x900
+#define _SECURE_ATL 1
+#endif
+[!if WTL_USE_STRING]
+[!if WTL_STRING_ATL]
+#include <atlstr.h>
+
+#define _WTL_NO_CSTRING
+[!else]
+
+#define _WTL_USE_CSTRING
+[!endif]
+[!else]
+
+#define _WTL_NO_CSTRING
+[!endif]
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+[!if WTL_ENABLE_AX]
+[!if WTL_EVC_COMPAT]
+#include <atlwin.h>
+#include <atlcom.h>
+[!endif]
+#include <atlhost.h>
+#include <atlctl.h>
+[!else]
+#include <atlwin.h>
+[!endif]
+
+[!if WTL_EVC_COMPAT]
+#if _WIN32_WCE >= 420
+#include <tpcshell.h>
+#endif
+[!else]
+#include <tpcshell.h>
+[!endif]
+#include <aygshell.h>
+#pragma comment(lib, "aygshell.lib")
+[!if WTL_USE_CPP_FILES]
+
+#include <atlframe.h>
+#include <atlctrls.h>
+[!if WTL_USE_VIEW && WTL_VIEWTYPE_PROPSHEET]
+#define _WTL_NEW_PAGE_NOTIFY_HANDLERS
+#include <atldlgs.h>
+[!endif]
+[!if WTL_USE_STRING && !WTL_STRING_ATL]
+#include <atlmisc.h>
+[!endif]
+[!if WTL_VIEW_SCROLL || WTL_VIEW_ZOOM]
+[!if !WTL_USE_STRING || WTL_STRING_ATL]
+#include <atlmisc.h>
+[!endif]
+#include <atlscrl.h>
+[!else]
+#define _WTL_CE_NO_ZOOMSCROLL
+[!endif]
+[!if !WTL_FULLSCREEN]
+#define _WTL_CE_NO_FULLSCREEN
+[!endif]
+#include <atlwince.h>
+[!endif]
diff --git a/include/WTL/AppWizMobile/Files/Templates/1033/toolbar.bmp b/include/WTL/AppWizMobile/Files/Templates/1033/toolbar.bmp
new file mode 100644 (file)
index 0000000..1057142
Binary files /dev/null and b/include/WTL/AppWizMobile/Files/Templates/1033/toolbar.bmp differ
diff --git a/include/WTL/AppWizMobile/Files/WTLMobile.ico b/include/WTL/AppWizMobile/Files/WTLMobile.ico
new file mode 100644 (file)
index 0000000..3bf85d3
Binary files /dev/null and b/include/WTL/AppWizMobile/Files/WTLMobile.ico differ
diff --git a/include/WTL/Include/atlapp.h b/include/WTL/Include/atlapp.h
new file mode 100644 (file)
index 0000000..c94f797
--- /dev/null
@@ -0,0 +1,1690 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLAPP_H__
+#define __ATLAPP_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLBASE_H__
+       #error atlapp.h requires atlbase.h to be included first
+#endif
+
+#ifndef _WIN32_WCE
+  #if (WINVER < 0x0400)
+       #error WTL requires Windows version 4.0 or higher
+  #endif
+
+  #if (_WIN32_IE < 0x0300)
+       #error WTL requires IE version 3.0 or higher
+  #endif
+#endif
+
+#ifdef _ATL_NO_COMMODULE
+       #error WTL requires that _ATL_NO_COMMODULE is not defined
+#endif // _ATL_NO_COMMODULE
+
+#if defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)
+       #pragma message("Warning: WTL for Windows CE doesn't use _ATL_MIN_CRT")
+#endif // defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)
+
+#include <limits.h>
+#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
+  #include <process.h> // for _beginthreadex
+#endif
+
+#if (_ATL_VER < 0x0800) && !defined(_DEBUG)
+  #include <stdio.h>
+#endif
+
+#include <commctrl.h>
+#ifndef _WIN32_WCE
+#pragma comment(lib, "comctl32.lib")
+#endif // !_WIN32_WCE
+
+#ifndef _WIN32_WCE
+  #include "atlres.h"
+#else // CE specific
+  #include "atlresce.h"
+#endif // _WIN32_WCE
+
+// We need to disable this warning because of template class arguments
+#pragma warning(disable: 4127)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// WTL version number
+
+#define _WTL_VER       0x0810
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CMessageFilter
+// CIdleHandler
+// CMessageLoop
+//
+// CAppModule
+// CServerAppModule
+//
+// Global functions:
+//   AtlGetDefaultGuiFont()
+//   AtlCreateBoldFont()
+//   AtlInitCommonControls()
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Global support for Windows CE
+
+#ifdef _WIN32_WCE
+
+#ifndef SW_SHOWDEFAULT
+  #define SW_SHOWDEFAULT       SW_SHOWNORMAL
+#endif // !SW_SHOWDEFAULT
+
+// These get's OR-ed in a constant and will have no effect.
+// Defining them reduces the number of #ifdefs required for CE.
+#define LR_DEFAULTSIZE      0
+#define LR_LOADFROMFILE     0
+
+#ifndef SM_CXCURSOR
+  #define SM_CXCURSOR             13
+#endif
+#ifndef SM_CYCURSOR
+  #define SM_CYCURSOR             14
+#endif
+
+inline BOOL IsMenu(HMENU hMenu)
+{
+       MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
+       ::SetLastError(0);
+       BOOL bRet = ::GetMenuItemInfo(hMenu, 0, TRUE, &mii);
+       if(!bRet)
+               bRet = (::GetLastError() != ERROR_INVALID_MENU_HANDLE) ? TRUE : FALSE;
+       return bRet;
+}
+
+#if (_WIN32_WCE >= 410)
+extern "C" void WINAPI ListView_SetItemSpacing(HWND hwndLV, int iHeight);
+#endif // (_WIN32_WCE >= 410)
+
+inline int MulDiv(IN int nNumber, IN int nNumerator, IN int nDenominator)
+{
+       __int64 multiple = nNumber * nNumerator;
+       return static_cast<int>(multiple / nDenominator);
+}
+
+#if (_ATL_VER >= 0x0800)
+
+#ifndef _WTL_KEEP_WS_OVERLAPPEDWINDOW
+  #ifdef WS_OVERLAPPEDWINDOW
+    #undef WS_OVERLAPPEDWINDOW
+    #define WS_OVERLAPPEDWINDOW        0
+  #endif // WS_OVERLAPPEDWINDOW
+#endif // !_WTL_KEEP_WS_OVERLAPPEDWINDOW
+
+#ifndef RDW_FRAME
+  #define RDW_FRAME    0
+#endif // !RDW_FRAME
+
+#ifndef WM_WINDOWPOSCHANGING
+  #define WM_WINDOWPOSCHANGING 0
+#endif // !WM_WINDOWPOSCHANGING
+
+#define FreeResource(x)
+#define UnlockResource(x)
+
+namespace ATL
+{
+  inline HRESULT CComModule::RegisterClassObjects(DWORD /*dwClsContext*/, DWORD /*dwFlags*/) throw()
+  { return E_NOTIMPL; }
+  inline HRESULT CComModule::RevokeClassObjects() throw()
+  { return E_NOTIMPL; }
+}; // namespace ATL
+
+#ifndef lstrlenW
+  #define lstrlenW     (int)ATL::lstrlenW
+#endif // lstrlenW
+
+inline int WINAPI lstrlenA(LPCSTR lpszString)
+{ return ATL::lstrlenA(lpszString); }
+
+#ifdef lstrcpyn
+  #undef lstrcpyn
+  #define lstrcpyn     ATL::lstrcpynW
+#endif // lstrcpyn
+
+#ifndef SetWindowLongPtrW
+  inline LONG_PTR tmp_SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
+  {
+       return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) );
+  }
+  #define SetWindowLongPtrW tmp_SetWindowLongPtrW
+#endif
+
+#ifndef GetWindowLongPtrW
+  inline LONG_PTR tmp_GetWindowLongPtrW( HWND hWnd, int nIndex )
+  {
+       return( ::GetWindowLongW( hWnd, nIndex ) );
+  }
+  #define GetWindowLongPtrW tmp_GetWindowLongPtrW
+#endif
+
+#ifndef LongToPtr
+  #define LongToPtr(x) ((void*)x)
+#endif
+
+#ifndef PtrToInt
+  #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
+#endif
+
+#else // !(_ATL_VER >= 0x0800)
+
+#ifdef lstrlenW
+  #undef lstrlenW
+  #define lstrlenW (int)::wcslen
+#endif // lstrlenW
+
+#define lstrlenA (int)strlen
+
+#ifndef lstrcpyn
+  inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength)
+  {
+       if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
+               return NULL;
+       int nLen = min(lstrlen(lpstrSrc), nLength - 1);
+       LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR));
+       lpstrDest[nLen] = 0;
+       return lpstrRet;
+  }
+#endif // !lstrcpyn
+
+#ifndef lstrcpynW
+  inline LPWSTR lstrcpynW(LPWSTR lpstrDest, LPCWSTR lpstrSrc, int nLength)
+  {
+       return lstrcpyn(lpstrDest, lpstrSrc, nLength);   // WinCE is Unicode only
+  }
+#endif // !lstrcpynW
+
+#ifndef lstrcpynA
+  inline LPSTR lstrcpynA(LPSTR lpstrDest, LPCSTR lpstrSrc, int nLength)
+  {
+       if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
+               return NULL;
+       int nLen = min(lstrlenA(lpstrSrc), nLength - 1);
+       LPSTR lpstrRet = (LPSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(char));
+       lpstrDest[nLen] = 0;
+       return lpstrRet;
+  }
+#endif // !lstrcpyn
+
+#ifdef TrackPopupMenu
+  #undef TrackPopupMenu
+#endif // TrackPopupMenu
+
+#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
+static CWndClassInfo& GetWndClassInfo() \
+{ \
+       static CWndClassInfo wc = \
+       { \
+               { style, StartWindowProc, \
+                 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
+               NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
+       }; \
+       return wc; \
+}
+
+#ifndef _MAX_FNAME
+  #define _MAX_FNAME   _MAX_PATH
+#endif // _MAX_FNAME
+
+#if (_WIN32_WCE < 400)
+  #define MAKEINTATOM(i)  (LPTSTR)((ULONG_PTR)((WORD)(i)))
+#endif // (_WIN32_WCE < 400)
+
+#if (_WIN32_WCE < 410)
+  #define WHEEL_PAGESCROLL                (UINT_MAX)
+  #define WHEEL_DELTA                     120
+#endif // (_WIN32_WCE < 410)
+
+#ifdef DrawIcon
+  #undef DrawIcon
+#endif
+
+#ifndef VARCMP_LT
+  #define VARCMP_LT   0
+#endif
+#ifndef VARCMP_EQ
+  #define VARCMP_EQ   1
+#endif
+#ifndef VARCMP_GT
+  #define VARCMP_GT   2
+#endif
+#ifndef VARCMP_NULL
+  #define VARCMP_NULL 3
+#endif
+
+#ifndef RDW_ALLCHILDREN
+  #define RDW_ALLCHILDREN   0
+#endif
+
+#endif // !(_ATL_VER >= 0x0800)
+
+#endif // _WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Global support for using original VC++ 6.0 headers with WTL
+
+#ifndef _ATL_NO_OLD_HEADERS_WIN64
+#if !defined(_WIN64) && (_ATL_VER < 0x0700)
+
+  #ifndef PSM_INSERTPAGE
+    #define PSM_INSERTPAGE          (WM_USER + 119)
+  #endif // !PSM_INSERTPAGE
+
+  #ifndef GetClassLongPtr
+    #define GetClassLongPtrA   GetClassLongA
+    #define GetClassLongPtrW   GetClassLongW
+    #ifdef UNICODE
+      #define GetClassLongPtr  GetClassLongPtrW
+    #else
+      #define GetClassLongPtr  GetClassLongPtrA
+    #endif // !UNICODE
+  #endif // !GetClassLongPtr
+
+  #ifndef GCLP_HICONSM
+    #define GCLP_HICONSM        (-34)
+  #endif // !GCLP_HICONSM
+
+  #ifndef GetWindowLongPtr
+    #define GetWindowLongPtrA   GetWindowLongA
+    #define GetWindowLongPtrW   GetWindowLongW
+    #ifdef UNICODE
+      #define GetWindowLongPtr  GetWindowLongPtrW
+    #else
+      #define GetWindowLongPtr  GetWindowLongPtrA
+    #endif // !UNICODE
+  #endif // !GetWindowLongPtr
+
+  #ifndef SetWindowLongPtr
+    #define SetWindowLongPtrA   SetWindowLongA
+    #define SetWindowLongPtrW   SetWindowLongW
+    #ifdef UNICODE
+      #define SetWindowLongPtr  SetWindowLongPtrW
+    #else
+      #define SetWindowLongPtr  SetWindowLongPtrA
+    #endif // !UNICODE
+  #endif // !SetWindowLongPtr
+
+  #ifndef GWLP_WNDPROC
+    #define GWLP_WNDPROC        (-4)
+  #endif
+  #ifndef GWLP_HINSTANCE
+    #define GWLP_HINSTANCE      (-6)
+  #endif
+  #ifndef GWLP_HWNDPARENT
+    #define GWLP_HWNDPARENT     (-8)
+  #endif
+  #ifndef GWLP_USERDATA
+    #define GWLP_USERDATA       (-21)
+  #endif
+  #ifndef GWLP_ID
+    #define GWLP_ID             (-12)
+  #endif
+
+  #ifndef DWLP_MSGRESULT
+    #define DWLP_MSGRESULT  0
+  #endif
+
+  typedef long LONG_PTR;
+  typedef unsigned long ULONG_PTR;
+  typedef ULONG_PTR DWORD_PTR;
+
+  #ifndef HandleToUlong
+    #define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )
+  #endif
+  #ifndef HandleToLong
+    #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
+  #endif
+  #ifndef LongToHandle
+    #define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))
+  #endif
+  #ifndef PtrToUlong
+    #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
+  #endif
+  #ifndef PtrToLong
+    #define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
+  #endif
+  #ifndef PtrToUint
+    #define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
+  #endif
+  #ifndef PtrToInt
+    #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
+  #endif
+  #ifndef PtrToUshort
+    #define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
+  #endif
+  #ifndef PtrToShort
+    #define PtrToShort( p ) ((short)(LONG_PTR)(p) )
+  #endif
+  #ifndef IntToPtr
+    #define IntToPtr( i )    ((VOID *)(INT_PTR)((int)i))
+  #endif
+  #ifndef UIntToPtr
+    #define UIntToPtr( ui )  ((VOID *)(UINT_PTR)((unsigned int)ui))
+  #endif
+  #ifndef LongToPtr
+    #define LongToPtr( l )   ((VOID *)(LONG_PTR)((long)l))
+  #endif
+  #ifndef ULongToPtr
+    #define ULongToPtr( ul )  ((VOID *)(ULONG_PTR)((unsigned long)ul))
+  #endif
+
+#endif // !defined(_WIN64) && (_ATL_VER < 0x0700)
+#endif // !_ATL_NO_OLD_HEADERS_WIN64
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Global support for SecureHelper functions
+
+#ifndef _TRUNCATE
+  #define _TRUNCATE ((size_t)-1)
+#endif
+
+#ifndef _ERRCODE_DEFINED
+  #define _ERRCODE_DEFINED
+  typedef int errno_t;
+#endif
+
+#ifndef _SECURECRT_ERRCODE_VALUES_DEFINED
+  #define _SECURECRT_ERRCODE_VALUES_DEFINED
+  #define EINVAL          22
+  #define STRUNCATE       80
+#endif
+
+#ifndef _countof
+  #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Miscellaneous global support
+
+// define useful macros from winuser.h
+#ifndef IS_INTRESOURCE
+  #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)
+#endif // IS_INTRESOURCE
+
+// protect template members from windowsx.h macros
+#ifdef _INC_WINDOWSX
+  #undef SubclassWindow
+#endif // _INC_WINDOWSX
+
+// define useful macros from windowsx.h
+#ifndef GET_X_LPARAM
+  #define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
+#endif
+#ifndef GET_Y_LPARAM
+  #define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
+#endif
+
+// Dummy structs for compiling with /CLR
+#if (_MSC_VER >= 1300) && defined(_MANAGED)
+  __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; }
+  __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; }
+  __if_not_exists(_PSP::_PSP) { struct _PSP { }; }
+#endif
+
+// Define ATLVERIFY macro for ATL3
+#if (_ATL_VER < 0x0700)
+  #ifndef ATLVERIFY
+    #ifdef _DEBUG
+      #define ATLVERIFY(expr) ATLASSERT(expr)
+    #else
+      #define ATLVERIFY(expr) (expr)
+    #endif // DEBUG
+  #endif // ATLVERIFY
+#endif // (_ATL_VER < 0x0700)
+
+// Forward declaration for ATL3 fix
+#if (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)
+  namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); };
+#endif
+
+
+namespace WTL
+{
+
+#if (_ATL_VER >= 0x0700)
+  DECLARE_TRACE_CATEGORY(atlTraceUI);
+  #ifdef _DEBUG
+    __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI"));
+  #endif // _DEBUG
+#else // !(_ATL_VER >= 0x0700)
+  enum wtlTraceFlags
+  {
+       atlTraceUI = 0x10000000
+  };
+#endif // !(_ATL_VER >= 0x0700)
+
+// Windows version helper
+inline bool AtlIsOldWindows()
+{
+       OSVERSIONINFO ovi = { 0 };
+       ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+       BOOL bRet = ::GetVersionEx(&ovi);
+       return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90)));
+}
+
+// default GUI font helper
+inline HFONT AtlGetDefaultGuiFont()
+{
+#ifndef _WIN32_WCE
+       return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
+#else // CE specific
+       return (HFONT)::GetStockObject(SYSTEM_FONT);
+#endif // _WIN32_WCE
+}
+
+// bold font helper (NOTE: Caller owns the font, and should destroy it when done using it)
+inline HFONT AtlCreateBoldFont(HFONT hFont = NULL)
+{
+       if(hFont == NULL)
+               hFont = AtlGetDefaultGuiFont();
+       ATLASSERT(hFont != NULL);
+       HFONT hFontBold = NULL;
+       LOGFONT lf = { 0 };
+       if(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT))
+       {
+               lf.lfWeight = FW_BOLD;
+               hFontBold =  ::CreateFontIndirect(&lf);
+               ATLASSERT(hFontBold != NULL);
+       }
+       else
+       {
+               ATLASSERT(FALSE);
+       }
+       return hFontBold;
+}
+
+// Common Controls initialization helper
+inline BOOL AtlInitCommonControls(DWORD dwFlags)
+{
+       INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags };
+       BOOL bRet = ::InitCommonControlsEx(&iccx);
+       ATLASSERT(bRet);
+       return bRet;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// RunTimeHelper - helper functions for Windows version and structure sizes
+
+// Not for Windows CE
+#if defined(_WIN32_WCE) && !defined(_WTL_NO_RUNTIME_STRUCT_SIZE)
+  #define _WTL_NO_RUNTIME_STRUCT_SIZE
+#endif
+
+#ifndef _WTL_NO_RUNTIME_STRUCT_SIZE
+
+#ifndef _SIZEOF_STRUCT
+  #define _SIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
+#endif
+
+#if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
+  #define REBARBANDINFO_V6_SIZE   _SIZEOF_STRUCT(REBARBANDINFO, cxHeader)
+#endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
+
+#if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
+  #define LVGROUP_V5_SIZE   _SIZEOF_STRUCT(LVGROUP, uAlign)
+#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
+
+#if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
+  #define LVTILEINFO_V5_SIZE   _SIZEOF_STRUCT(LVTILEINFO, puColumns)
+#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
+
+#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
+  #define MCHITTESTINFO_V1_SIZE   _SIZEOF_STRUCT(MCHITTESTINFO, st)
+#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
+
+#if !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
+  #define NONCLIENTMETRICS_V1_SIZE   _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont)
+#endif // !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
+
+#endif // !_WTL_NO_RUNTIME_STRUCT_SIZE
+
+namespace RunTimeHelper
+{
+#ifndef _WIN32_WCE
+       inline bool IsCommCtrl6()
+       {
+               DWORD dwMajor = 0, dwMinor = 0;
+               HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
+               return (SUCCEEDED(hRet) && (dwMajor >= 6));
+       }
+
+       inline bool IsVista()
+       {
+               OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
+               BOOL bRet = ::GetVersionEx(&ovi);
+               return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6));
+       }
+#endif // !_WIN32_WCE
+
+       inline int SizeOf_REBARBANDINFO()
+       {
+               int nSize = sizeof(REBARBANDINFO);
+#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
+               if(!(IsVista() && IsCommCtrl6()))
+                       nSize = REBARBANDINFO_V6_SIZE;
+#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
+               return nSize;
+       }
+
+#if (_WIN32_WINNT >= 0x501)
+       inline int SizeOf_LVGROUP()
+       {
+               int nSize = sizeof(LVGROUP);
+#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
+               if(!IsVista())
+                       nSize = LVGROUP_V5_SIZE;
+#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
+               return nSize;
+       }
+
+       inline int SizeOf_LVTILEINFO()
+       {
+               int nSize = sizeof(LVTILEINFO);
+#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
+               if(!IsVista())
+                       nSize = LVTILEINFO_V5_SIZE;
+#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
+               return nSize;
+       }
+#endif // (_WIN32_WINNT >= 0x501)
+
+       inline int SizeOf_MCHITTESTINFO()
+       {
+               int nSize = sizeof(MCHITTESTINFO);
+#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+               if(!(IsVista() && IsCommCtrl6()))
+                       nSize = MCHITTESTINFO_V1_SIZE;
+#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+               return nSize;
+       }
+
+#ifndef _WIN32_WCE
+       inline int SizeOf_NONCLIENTMETRICS()
+       {
+               int nSize = sizeof(NONCLIENTMETRICS);
+#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
+               if(!IsVista())
+                       nSize = NONCLIENTMETRICS_V1_SIZE;
+#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
+               return nSize;
+       }
+#endif // !_WIN32_WCE
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// ModuleHelper - helper functions for ATL3 and ATL7 module classes
+
+namespace ModuleHelper
+{
+       inline HINSTANCE GetModuleInstance()
+       {
+#if (_ATL_VER >= 0x0700)
+               return ATL::_AtlBaseModule.GetModuleInstance();
+#else // !(_ATL_VER >= 0x0700)
+               return ATL::_pModule->GetModuleInstance();
+#endif // !(_ATL_VER >= 0x0700)
+       }
+
+       inline HINSTANCE GetResourceInstance()
+       {
+#if (_ATL_VER >= 0x0700)
+               return ATL::_AtlBaseModule.GetResourceInstance();
+#else // !(_ATL_VER >= 0x0700)
+               return ATL::_pModule->GetResourceInstance();
+#endif // !(_ATL_VER >= 0x0700)
+       }
+
+       inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject)
+       {
+#if (_ATL_VER >= 0x0700)
+               ATL::_AtlWinModule.AddCreateWndData(pData, pObject);
+#else // !(_ATL_VER >= 0x0700)
+               ATL::_pModule->AddCreateWndData(pData, pObject);
+#endif // !(_ATL_VER >= 0x0700)
+       }
+
+       inline void* ExtractCreateWndData()
+       {
+#if (_ATL_VER >= 0x0700)
+               return ATL::_AtlWinModule.ExtractCreateWndData();
+#else // !(_ATL_VER >= 0x0700)
+               return ATL::_pModule->ExtractCreateWndData();
+#endif // !(_ATL_VER >= 0x0700)
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SecureHelper - helper functions for VS2005 secure CRT
+
+namespace SecureHelper
+{
+       inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
+       {
+#if _SECURE_ATL
+               ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc);
+#else
+               if(cchDest > (size_t)lstrlenA(lpstrSrc))
+                       ATLVERIFY(lstrcpyA(lpstrDest, lpstrSrc) != NULL);
+               else
+                       ATLASSERT(FALSE);
+#endif
+       }
+
+       inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
+       {
+#if _SECURE_ATL
+               ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc);
+#else
+               if(cchDest > (size_t)lstrlenW(lpstrSrc))
+                       ATLVERIFY(lstrcpyW(lpstrDest, lpstrSrc) != NULL);
+               else
+                       ATLASSERT(FALSE);
+#endif
+       }
+
+       inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
+       {
+#ifdef _UNICODE
+               strcpyW_x(lpstrDest, cchDest, lpstrSrc);
+#else
+               strcpyA_x(lpstrDest, cchDest, lpstrSrc);
+#endif
+       }
+
+       inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount)
+       {
+#if _SECURE_ATL
+               return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
+#else
+               errno_t nRet = 0;
+               if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
+               {
+                       nRet = EINVAL;
+               }
+               else if(cchCount == _TRUNCATE)
+               {
+                       cchCount = min(cchDest - 1, size_t(lstrlenA(lpstrSrc)));
+                       nRet = STRUNCATE;
+               }
+               else if(cchDest <= cchCount)
+               {
+                       lpstrDest[0] = 0;
+                       nRet = EINVAL;
+               }
+               if(nRet == 0 || nRet == STRUNCATE)
+                       nRet = (lstrcpynA(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
+               ATLASSERT(nRet == 0 || nRet == STRUNCATE);
+               return nRet;
+#endif
+       }
+
+       inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount)
+       {
+#if _SECURE_ATL
+               return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
+#else
+               errno_t nRet = 0;
+               if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
+               {
+                       nRet = EINVAL;
+               }
+               else if(cchCount == _TRUNCATE)
+               {
+                       cchCount = min(cchDest - 1, size_t(lstrlenW(lpstrSrc)));
+                       nRet = STRUNCATE;
+               }
+               else if(cchDest <= cchCount)
+               {
+                       lpstrDest[0] = 0;
+                       nRet = EINVAL;
+               }
+               if(nRet == 0 || nRet == STRUNCATE)
+                       nRet = (lstrcpynW(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
+               ATLASSERT(nRet == 0 || nRet == STRUNCATE);
+               return nRet;
+#endif
+       }
+
+       inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount)
+       {
+#ifdef _UNICODE
+               return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount);
+#else
+               return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount);
+#endif
+       }
+
+       inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
+       {
+#if _SECURE_ATL
+               ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc);
+#else
+               if(cchDest > (size_t)lstrlenA(lpstrSrc))
+                       ATLVERIFY(lstrcatA(lpstrDest, lpstrSrc) != NULL);
+               else
+                       ATLASSERT(FALSE);
+#endif
+       }
+
+       inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
+       {
+#if _SECURE_ATL
+               ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc);
+#else
+               if(cchDest > (size_t)lstrlenW(lpstrSrc))
+                       ATLVERIFY(lstrcatW(lpstrDest, lpstrSrc) != NULL);
+               else
+                       ATLASSERT(FALSE);
+#endif
+       }
+
+       inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
+       {
+#ifdef _UNICODE
+               strcatW_x(lpstrDest, cchDest, lpstrSrc);
+#else
+               strcatA_x(lpstrDest, cchDest, lpstrSrc);
+#endif
+       }
+
+       inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
+       {
+#if _SECURE_ATL
+               ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc);
+#else
+               if(cbDest >= cbSrc)
+                       memcpy(pDest, pSrc, cbSrc);
+               else
+                       ATLASSERT(FALSE);
+#endif
+       }
+
+       inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
+       {
+#if _SECURE_ATL
+               ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc);
+#else
+               if(cbDest >= cbSrc)
+                       memmove(pDest, pSrc, cbSrc);
+               else
+                       ATLASSERT(FALSE);
+#endif
+       }
+
+       inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
+       {
+#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
+               return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
+#else
+               cchBuff;   // Avoid unused argument warning
+#pragma warning(disable: 4996)
+               return _vstprintf(lpstrBuff, lpstrFormat, args);
+#pragma warning(default: 4996)
+#endif
+       }
+
+       inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
+       {
+#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
+               return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
+#else
+               cchBuff;   // Avoid unused argument warning
+               return ::wvsprintf(lpstrBuff, lpstrFormat, args);
+#endif
+       }
+
+       inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
+       {
+               va_list args;
+               va_start(args, lpstrFormat);
+               int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
+               va_end(args);
+               return nRes;
+       }
+
+       inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
+       {
+               va_list args;
+               va_start(args, lpstrFormat);
+               int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
+               va_end(args);
+               return nRes;
+       }
+}; // namespace SecureHelper
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMessageFilter - Interface for message filter support
+
+class CMessageFilter
+{
+public:
+       virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CIdleHandler - Interface for idle processing
+
+class CIdleHandler
+{
+public:
+       virtual BOOL OnIdle() = 0;
+};
+
+#ifndef _ATL_NO_OLD_NAMES
+  // for compatilibility with old names only
+  typedef CIdleHandler CUpdateUIObject;
+  #define DoUpdate OnIdle
+#endif // !_ATL_NO_OLD_NAMES
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMessageLoop - message loop implementation
+
+class CMessageLoop
+{
+public:
+       ATL::CSimpleArray<CMessageFilter*> m_aMsgFilter;
+       ATL::CSimpleArray<CIdleHandler*> m_aIdleHandler;
+       MSG m_msg;
+
+// Message filter operations
+       BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
+       {
+               return m_aMsgFilter.Add(pMessageFilter);
+       }
+
+       BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
+       {
+               return m_aMsgFilter.Remove(pMessageFilter);
+       }
+
+// Idle handler operations
+       BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
+       {
+               return m_aIdleHandler.Add(pIdleHandler);
+       }
+
+       BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
+       {
+               return m_aIdleHandler.Remove(pIdleHandler);
+       }
+
+#ifndef _ATL_NO_OLD_NAMES
+       // for compatilibility with old names only
+       BOOL AddUpdateUI(CIdleHandler* pIdleHandler)
+       {
+               ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
+               return AddIdleHandler(pIdleHandler);
+       }
+
+       BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)
+       {
+               ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
+               return RemoveIdleHandler(pIdleHandler);
+       }
+#endif // !_ATL_NO_OLD_NAMES
+
+// message loop
+       int Run()
+       {
+               BOOL bDoIdle = TRUE;
+               int nIdleCount = 0;
+               BOOL bRet;
+
+               for(;;)
+               {
+                       while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
+                       {
+                               if(!OnIdle(nIdleCount++))
+                                       bDoIdle = FALSE;
+                       }
+
+                       bRet = ::GetMessage(&m_msg, NULL, 0, 0);
+
+                       if(bRet == -1)
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
+                               continue;   // error, don't process
+                       }
+                       else if(!bRet)
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
+                               break;   // WM_QUIT, exit message loop
+                       }
+
+                       if(!PreTranslateMessage(&m_msg))
+                       {
+                               ::TranslateMessage(&m_msg);
+                               ::DispatchMessage(&m_msg);
+                       }
+
+                       if(IsIdleMessage(&m_msg))
+                       {
+                               bDoIdle = TRUE;
+                               nIdleCount = 0;
+                       }
+               }
+
+               return (int)m_msg.wParam;
+       }
+
+       static BOOL IsIdleMessage(MSG* pMsg)
+       {
+               // These messages should NOT cause idle processing
+               switch(pMsg->message)
+               {
+               case WM_MOUSEMOVE:
+#ifndef _WIN32_WCE
+               case WM_NCMOUSEMOVE:
+#endif // !_WIN32_WCE
+               case WM_PAINT:
+               case 0x0118:    // WM_SYSTIMER (caret blink)
+                       return FALSE;
+               }
+
+               return TRUE;
+       }
+
+// Overrideables
+       // Override to change message filtering
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               // loop backwards
+               for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
+               {
+                       CMessageFilter* pMessageFilter = m_aMsgFilter[i];
+                       if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
+                               return TRUE;
+               }
+               return FALSE;   // not translated
+       }
+
+       // override to change idle processing
+       virtual BOOL OnIdle(int /*nIdleCount*/)
+       {
+               for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
+               {
+                       CIdleHandler* pIdleHandler = m_aIdleHandler[i];
+                       if(pIdleHandler != NULL)
+                               pIdleHandler->OnIdle();
+               }
+               return FALSE;   // don't continue
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock
+// internal classes to manage critical sections for both ATL3 and ATL7
+
+class CStaticDataInitCriticalSectionLock
+{
+public:
+#if (_ATL_VER >= 0x0700)
+       ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
+
+       CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false)
+       { }
+#endif // (_ATL_VER >= 0x0700)
+
+       HRESULT Lock()
+       {
+#if (_ATL_VER >= 0x0700)
+               return m_cslock.Lock();
+#else // !(_ATL_VER >= 0x0700)
+               ::EnterCriticalSection(&ATL::_pModule->m_csStaticDataInit);
+               return S_OK;
+#endif // !(_ATL_VER >= 0x0700)
+       }
+
+       void Unlock()
+       {
+#if (_ATL_VER >= 0x0700)
+               m_cslock.Unlock();
+#else // !(_ATL_VER >= 0x0700)
+               ::LeaveCriticalSection(&ATL::_pModule->m_csStaticDataInit);
+#endif // !(_ATL_VER >= 0x0700)
+       }
+};
+
+
+class CWindowCreateCriticalSectionLock
+{
+public:
+#if (_ATL_VER >= 0x0700)
+       ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
+
+       CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false)
+       { }
+#endif // (_ATL_VER >= 0x0700)
+
+       HRESULT Lock()
+       {
+#if (_ATL_VER >= 0x0700)
+               return m_cslock.Lock();
+#else // !(_ATL_VER >= 0x0700)
+               ::EnterCriticalSection(&ATL::_pModule->m_csWindowCreate);
+               return S_OK;
+#endif // !(_ATL_VER >= 0x0700)
+       }
+
+       void Unlock()
+       {
+#if (_ATL_VER >= 0x0700)
+               m_cslock.Unlock();
+#else // !(_ATL_VER >= 0x0700)
+               ::LeaveCriticalSection(&ATL::_pModule->m_csWindowCreate);
+#endif // !(_ATL_VER >= 0x0700)
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTempBuffer - helper class for stack allocations for ATL3
+
+#ifndef _WTL_STACK_ALLOC_THRESHOLD
+  #define _WTL_STACK_ALLOC_THRESHOLD   512
+#endif
+
+#if (_ATL_VER >= 0x0700)
+
+using ATL::CTempBuffer;
+
+#else // !(_ATL_VER >= 0x0700)
+
+#ifndef SIZE_MAX
+  #ifdef _WIN64 
+    #define SIZE_MAX _UI64_MAX
+  #else
+    #define SIZE_MAX UINT_MAX
+  #endif
+#endif
+
+#pragma warning(disable: 4284)   // warning for operator ->
+
+template<typename T, int t_nFixedBytes = 128>
+class CTempBuffer
+{
+public:
+       CTempBuffer() : m_p(NULL)
+       {
+       }
+
+       CTempBuffer(size_t nElements) : m_p(NULL)
+       {
+               Allocate(nElements);
+       }
+
+       ~CTempBuffer()
+       {
+               if(m_p != reinterpret_cast<T*>(m_abFixedBuffer))
+                       free(m_p);
+       }
+
+       operator T*() const
+       {
+               return m_p;
+       }
+
+       T* operator ->() const
+       {
+               ATLASSERT(m_p != NULL);
+               return m_p;
+       }
+
+       T* Allocate(size_t nElements)
+       {
+               ATLASSERT(nElements <= (SIZE_MAX / sizeof(T)));
+               return AllocateBytes(nElements * sizeof(T));
+       }
+
+       T* AllocateBytes(size_t nBytes)
+       {
+               ATLASSERT(m_p == NULL);
+               if(nBytes > t_nFixedBytes)
+                       m_p = static_cast<T*>(malloc(nBytes));
+               else
+                       m_p = reinterpret_cast<T*>(m_abFixedBuffer);
+
+               return m_p;
+       }
+
+private:
+       T* m_p;
+       BYTE m_abFixedBuffer[t_nFixedBytes];
+};
+
+#pragma warning(default: 4284)
+
+#endif // !(_ATL_VER >= 0x0700)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppModule - module class for an application
+
+class CAppModule : public ATL::CComModule
+{
+public:
+       DWORD m_dwMainThreadID;
+       ATL::CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap;
+       ATL::CSimpleArray<HWND>* m_pSettingChangeNotify;
+
+// Overrides of CComModule::Init and Term
+       HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
+       {
+               HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);
+               if(FAILED(hRet))
+                       return hRet;
+
+               m_dwMainThreadID = ::GetCurrentThreadId();
+               typedef ATL::CSimpleMap<DWORD, CMessageLoop*>   _mapClass;
+               m_pMsgLoopMap = NULL;
+               ATLTRY(m_pMsgLoopMap = new _mapClass);
+               if(m_pMsgLoopMap == NULL)
+                       return E_OUTOFMEMORY;
+               m_pSettingChangeNotify = NULL;
+
+               return hRet;
+       }
+
+       void Term()
+       {
+               TermSettingChangeNotify();
+               delete m_pMsgLoopMap;
+               CComModule::Term();
+       }
+
+// Message loop map methods
+       BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
+       {
+               CStaticDataInitCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));
+                       ATLASSERT(FALSE);
+                       return FALSE;
+               }
+
+               ATLASSERT(pMsgLoop != NULL);
+               ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL);   // not in map yet
+
+               BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);
+
+               lock.Unlock();
+
+               return bRet;
+       }
+
+       BOOL RemoveMessageLoop()
+       {
+               CStaticDataInitCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n"));
+                       ATLASSERT(FALSE);
+                       return FALSE;
+               }
+
+               BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId());
+
+               lock.Unlock();
+
+               return bRet;
+       }
+
+       CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const
+       {
+               CStaticDataInitCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n"));
+                       ATLASSERT(FALSE);
+                       return NULL;
+               }
+
+               CMessageLoop* pLoop =  m_pMsgLoopMap->Lookup(dwThreadID);
+
+               lock.Unlock();
+
+               return pLoop;
+       }
+
+// Setting change notify methods
+       // Note: Call this from the main thread for MSDI apps
+       BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)
+       {
+               CStaticDataInitCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));
+                       ATLASSERT(FALSE);
+                       return FALSE;
+               }
+
+               if(m_pSettingChangeNotify == NULL)
+               {
+                       typedef ATL::CSimpleArray<HWND>   _notifyClass;
+                       ATLTRY(m_pSettingChangeNotify = new _notifyClass);
+                       ATLASSERT(m_pSettingChangeNotify != NULL);
+               }
+
+               BOOL bRet = (m_pSettingChangeNotify != NULL);
+               if(bRet && m_pSettingChangeNotify->GetSize() == 0)
+               {
+                       // init everything
+                       _ATL_EMPTY_DLGTEMPLATE templ;
+                       HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);
+                       ATLASSERT(::IsWindow(hNtfWnd));
+                       if(::IsWindow(hNtfWnd))
+                       {
+// need conditional code because types don't match in winuser.h
+#ifdef _WIN64
+                               ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
+#else
+                               ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this));
+#endif
+                               bRet = m_pSettingChangeNotify->Add(hNtfWnd);
+                       }
+                       else
+                       {
+                               bRet = FALSE;
+                       }
+               }
+
+               lock.Unlock();
+
+               return bRet;
+       }
+
+       void TermSettingChangeNotify()
+       {
+               CStaticDataInitCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));
+                       ATLASSERT(FALSE);
+                       return;
+               }
+
+               if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0)
+                       ::DestroyWindow((*m_pSettingChangeNotify)[0]);
+               delete m_pSettingChangeNotify;
+               m_pSettingChangeNotify = NULL;
+
+               lock.Unlock();
+       }
+
+       BOOL AddSettingChangeNotify(HWND hWnd)
+       {
+               CStaticDataInitCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));
+                       ATLASSERT(FALSE);
+                       return FALSE;
+               }
+
+               ATLASSERT(::IsWindow(hWnd));
+               BOOL bRet = FALSE;
+               if(InitSettingChangeNotify() != FALSE)
+                       bRet = m_pSettingChangeNotify->Add(hWnd);
+
+               lock.Unlock();
+
+               return bRet;
+       }
+
+       BOOL RemoveSettingChangeNotify(HWND hWnd)
+       {
+               CStaticDataInitCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));
+                       ATLASSERT(FALSE);
+                       return FALSE;
+               }
+
+               BOOL bRet = FALSE;
+               if(m_pSettingChangeNotify != NULL)
+                       bRet = m_pSettingChangeNotify->Remove(hWnd);
+
+               lock.Unlock();
+
+               return bRet;
+       }
+
+// Implementation - setting change notify dialog template and dialog procedure
+       struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE
+       {
+               _ATL_EMPTY_DLGTEMPLATE()
+               {
+                       memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));
+                       style = WS_POPUP;
+               }
+               WORD wMenu, wClass, wTitle;
+       };
+
+#ifdef _WIN64
+       static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+#else
+       static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+#endif
+       {
+               if(uMsg == WM_SETTINGCHANGE)
+               {
+// need conditional code because types don't match in winuser.h
+#ifdef _WIN64
+                       CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
+#else
+                       CAppModule* pModule = (CAppModule*)LongToPtr(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
+#endif
+                       ATLASSERT(pModule != NULL);
+                       ATLASSERT(pModule->m_pSettingChangeNotify != NULL);
+                       const UINT uTimeout = 1500;   // ms
+                       for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)
+                       {
+#if !defined(_WIN32_WCE)
+                               ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL);
+#elif(_WIN32_WCE >= 400) // CE specific
+                               ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_NORMAL, uTimeout, NULL);
+#else // _WIN32_WCE < 400 specific
+                               uTimeout;
+                               ::SendMessage((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam);
+#endif
+                       }
+                       return TRUE;
+               }
+               return FALSE;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CServerAppModule - module class for a COM server application
+
+class CServerAppModule : public CAppModule
+{
+public:
+       HANDLE m_hEventShutdown;
+       bool m_bActivity;
+       DWORD m_dwTimeOut;
+       DWORD m_dwPause;
+
+// Override of CAppModule::Init
+       HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
+       {
+               m_dwTimeOut = 5000;
+               m_dwPause = 1000;
+               return CAppModule::Init(pObjMap, hInstance, pLibID);
+       }
+
+       void Term()
+       {
+               if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown))
+                       m_hEventShutdown = NULL;
+               CAppModule::Term();
+       }
+
+// COM Server methods
+       LONG Unlock()
+       {
+               LONG lRet = CComModule::Unlock();
+               if(lRet == 0)
+               {
+                       m_bActivity = true;
+                       ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
+               }
+               return lRet;
+       }
+
+       void MonitorShutdown()
+       {
+               for(;;)
+               {
+                       ::WaitForSingleObject(m_hEventShutdown, INFINITE);
+                       DWORD dwWait = 0;
+                       do
+                       {
+                               m_bActivity = false;
+                               dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);
+                       }
+                       while(dwWait == WAIT_OBJECT_0);
+                       // timed out
+                       if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail
+                       {
+#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) && defined(_ATL_FREE_THREADED) && !defined(_WIN32_WCE)
+                               ::CoSuspendClassObjects();
+                               if(!m_bActivity && m_nLockCnt == 0)
+#endif
+                                       break;
+                       }
+               }
+               // This handle should be valid now. If it isn't, 
+               // check if _Module.Term was called first (it shouldn't)
+               if(::CloseHandle(m_hEventShutdown))
+                       m_hEventShutdown = NULL;
+               ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
+       }
+
+       bool StartMonitor()
+       {
+               m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);
+               if(m_hEventShutdown == NULL)
+                       return false;
+               DWORD dwThreadID = 0;
+#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
+               HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);
+#else
+               HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
+#endif
+               bool bRet = (hThread != NULL);
+               if(bRet)
+                       ::CloseHandle(hThread);
+               return bRet;
+       }
+
+       static DWORD WINAPI MonitorProc(void* pv)
+       {
+               CServerAppModule* p = (CServerAppModule*)pv;
+               p->MonitorShutdown();
+               return 0;
+       }
+
+#if (_ATL_VER < 0x0700)
+       // search for an occurence of string p2 in string p1
+       static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
+       {
+               while(p1 != NULL && *p1 != NULL)
+               {
+                       LPCTSTR p = p2;
+                       while(p != NULL && *p != NULL)
+                       {
+                               if(*p1 == *p)
+                                       return ::CharNext(p1);
+                               p = ::CharNext(p);
+                       }
+                       p1 = ::CharNext(p1);
+               }
+               return NULL;
+       }
+#endif // (_ATL_VER < 0x0700)
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CString forward reference (enables CString use in atluser.h and atlgdi.h)
+
+#if defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
+  #define _WTL_USE_CSTRING
+#endif // defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
+
+#ifdef _WTL_USE_CSTRING
+  class CString;   // forward declaration (include atlmisc.h for the whole class)
+#endif // _WTL_USE_CSTRING
+
+// CString namespace
+#ifndef _CSTRING_NS
+  #ifdef __ATLSTR_H__
+    #define _CSTRING_NS        ATL
+  #else
+    #define _CSTRING_NS        WTL
+  #endif
+#endif // _CSTRING_NS
+
+// Type classes namespace
+#ifndef _WTYPES_NS
+  #ifdef __ATLTYPES_H__
+    #define _WTYPES_NS
+  #else
+    #define _WTYPES_NS WTL
+  #endif
+#endif // _WTYPES_NS
+
+}; // namespace WTL
+
+
+///////////////////////////////////////////////////////////////////////////////
+// General DLL version helpers (excluded from atlbase.h if _ATL_DLL is defined)
+
+#if (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)
+
+namespace ATL
+{
+
+inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo)
+{
+       ATLASSERT(pDllVersionInfo != NULL);
+       if(pDllVersionInfo == NULL)
+               return E_INVALIDARG;
+
+       // We must get this function explicitly because some DLLs don't implement it.
+       DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion");
+       if(pfnDllGetVersion == NULL)
+               return E_NOTIMPL;
+
+       return (*pfnDllGetVersion)(pDllVersionInfo);
+}
+
+inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo)
+{
+       HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName);
+       if(hInstDLL == NULL)
+               return E_FAIL;
+       HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo);
+       ::FreeLibrary(hInstDLL);
+       return hRet;
+}
+
+// Common Control Versions:
+//   Win95/WinNT 4.0    maj=4 min=00
+//   IE 3.x     maj=4 min=70
+//   IE 4.0     maj=4 min=71
+inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
+{
+       ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
+       if(pdwMajor == NULL || pdwMinor == NULL)
+               return E_INVALIDARG;
+
+       DLLVERSIONINFO dvi;
+       ::ZeroMemory(&dvi, sizeof(dvi));
+       dvi.cbSize = sizeof(dvi);
+       HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi);
+
+       if(SUCCEEDED(hRet))
+       {
+               *pdwMajor = dvi.dwMajorVersion;
+               *pdwMinor = dvi.dwMinorVersion;
+       }
+       else if(hRet == E_NOTIMPL)
+       {
+               // If DllGetVersion is not there, then the DLL is a version
+               // previous to the one shipped with IE 3.x
+               *pdwMajor = 4;
+               *pdwMinor = 0;
+               hRet = S_OK;
+       }
+
+       return hRet;
+}
+
+// Shell Versions:
+//   Win95/WinNT 4.0                    maj=4 min=00
+//   IE 3.x, IE 4.0 without Web Integrated Desktop  maj=4 min=00
+//   IE 4.0 with Web Integrated Desktop         maj=4 min=71
+//   IE 4.01 with Web Integrated Desktop        maj=4 min=72
+inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
+{
+       ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
+       if(pdwMajor == NULL || pdwMinor == NULL)
+               return E_INVALIDARG;
+
+       DLLVERSIONINFO dvi;
+       ::ZeroMemory(&dvi, sizeof(dvi));
+       dvi.cbSize = sizeof(dvi);
+       HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi);
+
+       if(SUCCEEDED(hRet))
+       {
+               *pdwMajor = dvi.dwMajorVersion;
+               *pdwMinor = dvi.dwMinorVersion;
+       }
+       else if(hRet == E_NOTIMPL)
+       {
+               // If DllGetVersion is not there, then the DLL is a version
+               // previous to the one shipped with IE 4.x
+               *pdwMajor = 4;
+               *pdwMinor = 0;
+               hRet = S_OK;
+       }
+
+       return hRet;
+}
+
+}; // namespace ATL
+
+#endif // (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)
+
+
+// These are always included
+#include "atlwinx.h"
+#include "atluser.h"
+#include "atlgdi.h"
+
+#ifndef _WTL_NO_AUTOMATIC_NAMESPACE
+using namespace WTL;
+#endif // !_WTL_NO_AUTOMATIC_NAMESPACE
+
+#endif // __ATLAPP_H__
diff --git a/include/WTL/Include/atlcrack.h b/include/WTL/Include/atlcrack.h
new file mode 100644 (file)
index 0000000..90f7560
--- /dev/null
@@ -0,0 +1,2380 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLCRACK_H__
+#define __ATLCRACK_H__
+
+#pragma once
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Message map macro for cracked handlers
+
+// Note about message maps with cracked handlers:
+// For ATL 3.0, a message map using cracked handlers MUST use BEGIN_MSG_MAP_EX.
+// For ATL 7.0 or higher, you can use BEGIN_MSG_MAP for CWindowImpl/CDialogImpl derived classes,
+// but must use BEGIN_MSG_MAP_EX for classes that don't derive from CWindowImpl/CDialogImpl.
+
+#define BEGIN_MSG_MAP_EX(theClass) \
+public: \
+       BOOL m_bMsgHandled; \
+       /* "handled" management for cracked handlers */ \
+       BOOL IsMsgHandled() const \
+       { \
+               return m_bMsgHandled; \
+       } \
+       void SetMsgHandled(BOOL bHandled) \
+       { \
+               m_bMsgHandled = bHandled; \
+       } \
+       BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
+       { \
+               BOOL bOldMsgHandled = m_bMsgHandled; \
+               BOOL bRet = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); \
+               m_bMsgHandled = bOldMsgHandled; \
+               return bRet; \
+       } \
+       BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) \
+       { \
+               BOOL bHandled = TRUE; \
+               hWnd; \
+               uMsg; \
+               wParam; \
+               lParam; \
+               lResult; \
+               bHandled; \
+               switch(dwMsgMapID) \
+               { \
+               case 0:
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Standard Windows message macros
+
+// int OnCreate(LPCREATESTRUCT lpCreateStruct)
+#define MSG_WM_CREATE(func) \
+       if (uMsg == WM_CREATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
+#define MSG_WM_INITDIALOG(func) \
+       if (uMsg == WM_INITDIALOG) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HWND)wParam, lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnCopyData(CWindow wnd, PCOPYDATASTRUCT pCopyDataStruct)
+#define MSG_WM_COPYDATA(func) \
+       if (uMsg == WM_COPYDATA) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HWND)wParam, (PCOPYDATASTRUCT)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDestroy()
+#define MSG_WM_DESTROY(func) \
+       if (uMsg == WM_DESTROY) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMove(CPoint ptPos)
+#define MSG_WM_MOVE(func) \
+       if (uMsg == WM_MOVE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSize(UINT nType, CSize size)
+#define MSG_WM_SIZE(func) \
+       if (uMsg == WM_SIZE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnActivate(UINT nState, BOOL bMinimized, CWindow wndOther)
+#define MSG_WM_ACTIVATE(func) \
+       if (uMsg == WM_ACTIVATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)LOWORD(wParam), (BOOL)HIWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSetFocus(CWindow wndOld)
+#define MSG_WM_SETFOCUS(func) \
+       if (uMsg == WM_SETFOCUS) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnKillFocus(CWindow wndFocus)
+#define MSG_WM_KILLFOCUS(func) \
+       if (uMsg == WM_KILLFOCUS) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnEnable(BOOL bEnable)
+#define MSG_WM_ENABLE(func) \
+       if (uMsg == WM_ENABLE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnPaint(CDCHandle dc)
+#define MSG_WM_PAINT(func) \
+       if (uMsg == WM_PAINT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HDC)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnClose()
+#define MSG_WM_CLOSE(func) \
+       if (uMsg == WM_CLOSE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnQueryEndSession(UINT nSource, UINT uLogOff)
+#define MSG_WM_QUERYENDSESSION(func) \
+       if (uMsg == WM_QUERYENDSESSION) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)wParam, (UINT)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnQueryOpen()
+#define MSG_WM_QUERYOPEN(func) \
+       if (uMsg == WM_QUERYOPEN) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func(); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnEraseBkgnd(CDCHandle dc)
+#define MSG_WM_ERASEBKGND(func) \
+       if (uMsg == WM_ERASEBKGND) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSysColorChange()
+#define MSG_WM_SYSCOLORCHANGE(func) \
+       if (uMsg == WM_SYSCOLORCHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnEndSession(BOOL bEnding, UINT uLogOff)
+#define MSG_WM_ENDSESSION(func) \
+       if (uMsg == WM_ENDSESSION) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)wParam, (UINT)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnShowWindow(BOOL bShow, UINT nStatus)
+#define MSG_WM_SHOWWINDOW(func) \
+       if (uMsg == WM_SHOWWINDOW) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)wParam, (int)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnCtlColorEdit(CDCHandle dc, CEdit edit)
+#define MSG_WM_CTLCOLOREDIT(func) \
+       if (uMsg == WM_CTLCOLOREDIT) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnCtlColorListBox(CDCHandle dc, CListBox listBox)
+#define MSG_WM_CTLCOLORLISTBOX(func) \
+       if (uMsg == WM_CTLCOLORLISTBOX) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnCtlColorBtn(CDCHandle dc, CButton button)
+#define MSG_WM_CTLCOLORBTN(func) \
+       if (uMsg == WM_CTLCOLORBTN) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnCtlColorDlg(CDCHandle dc, CWindow wnd)
+#define MSG_WM_CTLCOLORDLG(func) \
+       if (uMsg == WM_CTLCOLORDLG) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar)
+#define MSG_WM_CTLCOLORSCROLLBAR(func) \
+       if (uMsg == WM_CTLCOLORSCROLLBAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnCtlColorStatic(CDCHandle dc, CStatic wndStatic)
+#define MSG_WM_CTLCOLORSTATIC(func) \
+       if (uMsg == WM_CTLCOLORSTATIC) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
+#define MSG_WM_SETTINGCHANGE(func) \
+       if (uMsg == WM_SETTINGCHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPCTSTR)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDevModeChange(LPCTSTR lpDeviceName)
+#define MSG_WM_DEVMODECHANGE(func) \
+       if (uMsg == WM_DEVMODECHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((LPCTSTR)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnActivateApp(BOOL bActive, DWORD dwThreadID)
+#define MSG_WM_ACTIVATEAPP(func) \
+       if (uMsg == WM_ACTIVATEAPP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)wParam, (DWORD)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnFontChange()
+#define MSG_WM_FONTCHANGE(func) \
+       if (uMsg == WM_FONTCHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnTimeChange()
+#define MSG_WM_TIMECHANGE(func) \
+       if (uMsg == WM_TIMECHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCancelMode()
+#define MSG_WM_CANCELMODE(func) \
+       if (uMsg == WM_CANCELMODE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message)
+#define MSG_WM_SETCURSOR(func) \
+       if (uMsg == WM_SETCURSOR) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnMouseActivate(CWindow wndTopLevel, UINT nHitTest, UINT message)
+#define MSG_WM_MOUSEACTIVATE(func) \
+       if (uMsg == WM_MOUSEACTIVATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnChildActivate()
+#define MSG_WM_CHILDACTIVATE(func) \
+       if (uMsg == WM_CHILDACTIVATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnGetMinMaxInfo(LPMINMAXINFO lpMMI)
+#define MSG_WM_GETMINMAXINFO(func) \
+       if (uMsg == WM_GETMINMAXINFO) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((LPMINMAXINFO)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnIconEraseBkgnd(CDCHandle dc)
+#define MSG_WM_ICONERASEBKGND(func) \
+       if (uMsg == WM_ICONERASEBKGND) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HDC)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSpoolerStatus(UINT nStatus, UINT nJobs)
+#define MSG_WM_SPOOLERSTATUS(func) \
+       if (uMsg == WM_SPOOLERSTATUS) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (UINT)LOWORD(lParam)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
+#define MSG_WM_DRAWITEM(func) \
+       if (uMsg == WM_DRAWITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
+#define MSG_WM_MEASUREITEM(func) \
+       if (uMsg == WM_MEASUREITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct)
+#define MSG_WM_DELETEITEM(func) \
+       if (uMsg == WM_DELETEITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+//int OnCharToItem(UINT nChar, UINT nIndex, CListBox listBox)
+#define MSG_WM_CHARTOITEM(func) \
+       if (uMsg == WM_CHARTOITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox)
+#define MSG_WM_VKEYTOITEM(func) \
+       if (uMsg == WM_VKEYTOITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HCURSOR OnQueryDragIcon()
+#define MSG_WM_QUERYDRAGICON(func) \
+       if (uMsg == WM_QUERYDRAGICON) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func(); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
+#define MSG_WM_COMPAREITEM(func) \
+       if (uMsg == WM_COMPAREITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCompacting(UINT nCpuTime)
+#define MSG_WM_COMPACTING(func) \
+       if (uMsg == WM_COMPACTING) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct)
+#define MSG_WM_NCCREATE(func) \
+       if (uMsg == WM_NCCREATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcDestroy()
+#define MSG_WM_NCDESTROY(func) \
+       if (uMsg == WM_NCDESTROY) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam)
+#define MSG_WM_NCCALCSIZE(func) \
+       if (uMsg == WM_NCCALCSIZE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((BOOL)wParam, lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// UINT OnNcHitTest(CPoint point)
+#define MSG_WM_NCHITTEST(func) \
+       if (uMsg == WM_NCHITTEST) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcPaint(CRgn rgn)
+#define MSG_WM_NCPAINT(func) \
+       if (uMsg == WM_NCPAINT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HRGN)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnNcActivate(BOOL bActive)
+#define MSG_WM_NCACTIVATE(func) \
+       if (uMsg == WM_NCACTIVATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((BOOL)wParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// UINT OnGetDlgCode(LPMSG lpMsg)
+#define MSG_WM_GETDLGCODE(func) \
+       if (uMsg == WM_GETDLGCODE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((LPMSG)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcMouseMove(UINT nHitTest, CPoint point)
+#define MSG_WM_NCMOUSEMOVE(func) \
+       if (uMsg == WM_NCMOUSEMOVE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcLButtonDown(UINT nHitTest, CPoint point)
+#define MSG_WM_NCLBUTTONDOWN(func) \
+       if (uMsg == WM_NCLBUTTONDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcLButtonUp(UINT nHitTest, CPoint point)
+#define MSG_WM_NCLBUTTONUP(func) \
+       if (uMsg == WM_NCLBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcLButtonDblClk(UINT nHitTest, CPoint point)
+#define MSG_WM_NCLBUTTONDBLCLK(func) \
+       if (uMsg == WM_NCLBUTTONDBLCLK) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcRButtonDown(UINT nHitTest, CPoint point)
+#define MSG_WM_NCRBUTTONDOWN(func) \
+       if (uMsg == WM_NCRBUTTONDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcRButtonUp(UINT nHitTest, CPoint point)
+#define MSG_WM_NCRBUTTONUP(func) \
+       if (uMsg == WM_NCRBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcRButtonDblClk(UINT nHitTest, CPoint point)
+#define MSG_WM_NCRBUTTONDBLCLK(func) \
+       if (uMsg == WM_NCRBUTTONDBLCLK) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcMButtonDown(UINT nHitTest, CPoint point)
+#define MSG_WM_NCMBUTTONDOWN(func) \
+       if (uMsg == WM_NCMBUTTONDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcMButtonUp(UINT nHitTest, CPoint point)
+#define MSG_WM_NCMBUTTONUP(func) \
+       if (uMsg == WM_NCMBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNcMButtonDblClk(UINT nHitTest, CPoint point)
+#define MSG_WM_NCMBUTTONDBLCLK(func) \
+       if (uMsg == WM_NCMBUTTONDBLCLK) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_KEYDOWN(func) \
+       if (uMsg == WM_KEYDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_KEYUP(func) \
+       if (uMsg == WM_KEYUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_CHAR(func) \
+       if (uMsg == WM_CHAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_DEADCHAR(func) \
+       if (uMsg == WM_DEADCHAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_SYSKEYDOWN(func) \
+       if (uMsg == WM_SYSKEYDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_SYSKEYUP(func) \
+       if (uMsg == WM_SYSKEYUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_SYSCHAR(func) \
+       if (uMsg == WM_SYSCHAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSysDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_SYSDEADCHAR(func) \
+       if (uMsg == WM_SYSDEADCHAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSysCommand(UINT nID, LPARAM lParam)
+#define MSG_WM_SYSCOMMAND(func) \
+       if (uMsg == WM_SYSCOMMAND) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnTCard(UINT idAction, DWORD dwActionData)
+#define MSG_WM_TCARD(func) \
+       if (uMsg == WM_TCARD) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (DWORD)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnTimer(UINT_PTR nIDEvent)
+#define MSG_WM_TIMER(func) \
+       if (uMsg == WM_TIMER) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT_PTR)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
+#define MSG_WM_HSCROLL(func) \
+       if (uMsg == WM_HSCROLL) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
+#define MSG_WM_VSCROLL(func) \
+       if (uMsg == WM_VSCROLL) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnInitMenu(CMenu menu)
+#define MSG_WM_INITMENU(func) \
+       if (uMsg == WM_INITMENU) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HMENU)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnInitMenuPopup(CMenu menuPopup, UINT nIndex, BOOL bSysMenu)
+#define MSG_WM_INITMENUPOPUP(func) \
+       if (uMsg == WM_INITMENUPOPUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HMENU)wParam, (UINT)LOWORD(lParam), (BOOL)HIWORD(lParam)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMenuSelect(UINT nItemID, UINT nFlags, CMenu menu)
+#define MSG_WM_MENUSELECT(func) \
+       if (uMsg == WM_MENUSELECT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnMenuChar(UINT nChar, UINT nFlags, CMenu menu)
+#define MSG_WM_MENUCHAR(func) \
+       if (uMsg == WM_MENUCHAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((TCHAR)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnNotify(int idCtrl, LPNMHDR pnmh)
+#define MSG_WM_NOTIFY(func) \
+       if (uMsg == WM_NOTIFY) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((int)wParam, (LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnEnterIdle(UINT nWhy, CWindow wndWho)
+#define MSG_WM_ENTERIDLE(func) \
+       if (uMsg == WM_ENTERIDLE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMouseMove(UINT nFlags, CPoint point)
+#define MSG_WM_MOUSEMOVE(func) \
+       if (uMsg == WM_MOUSEMOVE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
+#define MSG_WM_MOUSEWHEEL(func) \
+       if (uMsg == WM_MOUSEWHEEL) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)LOWORD(wParam), (short)HIWORD(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnLButtonDown(UINT nFlags, CPoint point)
+#define MSG_WM_LBUTTONDOWN(func) \
+       if (uMsg == WM_LBUTTONDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnLButtonUp(UINT nFlags, CPoint point)
+#define MSG_WM_LBUTTONUP(func) \
+       if (uMsg == WM_LBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnLButtonDblClk(UINT nFlags, CPoint point)
+#define MSG_WM_LBUTTONDBLCLK(func) \
+       if (uMsg == WM_LBUTTONDBLCLK) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnRButtonDown(UINT nFlags, CPoint point)
+#define MSG_WM_RBUTTONDOWN(func) \
+       if (uMsg == WM_RBUTTONDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnRButtonUp(UINT nFlags, CPoint point)
+#define MSG_WM_RBUTTONUP(func) \
+       if (uMsg == WM_RBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnRButtonDblClk(UINT nFlags, CPoint point)
+#define MSG_WM_RBUTTONDBLCLK(func) \
+       if (uMsg == WM_RBUTTONDBLCLK) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMButtonDown(UINT nFlags, CPoint point)
+#define MSG_WM_MBUTTONDOWN(func) \
+       if (uMsg == WM_MBUTTONDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMButtonUp(UINT nFlags, CPoint point)
+#define MSG_WM_MBUTTONUP(func) \
+       if (uMsg == WM_MBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMButtonDblClk(UINT nFlags, CPoint point)
+#define MSG_WM_MBUTTONDBLCLK(func) \
+       if (uMsg == WM_MBUTTONDBLCLK) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnParentNotify(UINT message, UINT nChildID, LPARAM lParam)
+#define MSG_WM_PARENTNOTIFY(func) \
+       if (uMsg == WM_PARENTNOTIFY) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMDIActivate(CWindow wndActivate, CWindow wndDeactivate)
+#define MSG_WM_MDIACTIVATE(func) \
+       if (uMsg == WM_MDIACTIVATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam, (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnRenderFormat(UINT nFormat)
+#define MSG_WM_RENDERFORMAT(func) \
+       if (uMsg == WM_RENDERFORMAT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnRenderAllFormats()
+#define MSG_WM_RENDERALLFORMATS(func) \
+       if (uMsg == WM_RENDERALLFORMATS) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDestroyClipboard()
+#define MSG_WM_DESTROYCLIPBOARD(func) \
+       if (uMsg == WM_DESTROYCLIPBOARD) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDrawClipboard()
+#define MSG_WM_DRAWCLIPBOARD(func) \
+       if (uMsg == WM_DRAWCLIPBOARD) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnPaintClipboard(CWindow wndViewer, const LPPAINTSTRUCT lpPaintStruct)
+#define MSG_WM_PAINTCLIPBOARD(func) \
+       if (uMsg == WM_PAINTCLIPBOARD) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam, (const LPPAINTSTRUCT)::GlobalLock((HGLOBAL)lParam)); \
+               ::GlobalUnlock((HGLOBAL)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnVScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos)
+#define MSG_WM_VSCROLLCLIPBOARD(func) \
+       if (uMsg == WM_VSCROLLCLIPBOARD) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnContextMenu(CWindow wnd, CPoint point)
+#define MSG_WM_CONTEXTMENU(func) \
+       if (uMsg == WM_CONTEXTMENU) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSizeClipboard(CWindow wndViewer, const LPRECT lpRect)
+#define MSG_WM_SIZECLIPBOARD(func) \
+       if (uMsg == WM_SIZECLIPBOARD) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam, (const LPRECT)::GlobalLock((HGLOBAL)lParam)); \
+               ::GlobalUnlock((HGLOBAL)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnAskCbFormatName(UINT nMaxCount, LPTSTR lpszString)
+#define MSG_WM_ASKCBFORMATNAME(func) \
+       if (uMsg == WM_ASKCBFORMATNAME) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((DWORD)wParam, (LPTSTR)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnChangeCbChain(CWindow wndRemove, CWindow wndAfter)
+#define MSG_WM_CHANGECBCHAIN(func) \
+       if (uMsg == WM_CHANGECBCHAIN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam, (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnHScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos)
+#define MSG_WM_HSCROLLCLIPBOARD(func) \
+       if (uMsg == WM_HSCROLLCLIPBOARD) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnQueryNewPalette()
+#define MSG_WM_QUERYNEWPALETTE(func) \
+       if (uMsg == WM_QUERYNEWPALETTE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func(); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnPaletteChanged(CWindow wndFocus)
+#define MSG_WM_PALETTECHANGED(func) \
+       if (uMsg == WM_PALETTECHANGED) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnPaletteIsChanging(CWindow wndPalChg)
+#define MSG_WM_PALETTEISCHANGING(func) \
+       if (uMsg == WM_PALETTEISCHANGING) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDropFiles(HDROP hDropInfo)
+#define MSG_WM_DROPFILES(func) \
+       if (uMsg == WM_DROPFILES) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HDROP)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnWindowPosChanging(LPWINDOWPOS lpWndPos)
+#define MSG_WM_WINDOWPOSCHANGING(func) \
+       if (uMsg == WM_WINDOWPOSCHANGING) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((LPWINDOWPOS)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnWindowPosChanged(LPWINDOWPOS lpWndPos)
+#define MSG_WM_WINDOWPOSCHANGED(func) \
+       if (uMsg == WM_WINDOWPOSCHANGED) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((LPWINDOWPOS)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnExitMenuLoop(BOOL fIsTrackPopupMenu)
+#define MSG_WM_EXITMENULOOP(func) \
+       if (uMsg == WM_EXITMENULOOP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnEnterMenuLoop(BOOL fIsTrackPopupMenu)
+#define MSG_WM_ENTERMENULOOP(func) \
+       if (uMsg == WM_ENTERMENULOOP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
+#define MSG_WM_STYLECHANGED(func) \
+       if (uMsg == WM_STYLECHANGED) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPSTYLESTRUCT)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
+#define MSG_WM_STYLECHANGING(func) \
+       if (uMsg == WM_STYLECHANGING) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPSTYLESTRUCT)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSizing(UINT fwSide, LPRECT pRect)
+#define MSG_WM_SIZING(func) \
+       if (uMsg == WM_SIZING) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPRECT)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMoving(UINT fwSide, LPRECT pRect)
+#define MSG_WM_MOVING(func) \
+       if (uMsg == WM_MOVING) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPRECT)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCaptureChanged(CWindow wnd)
+#define MSG_WM_CAPTURECHANGED(func) \
+       if (uMsg == WM_CAPTURECHANGED) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnDeviceChange(UINT nEventType, DWORD dwData)
+#define MSG_WM_DEVICECHANGE(func) \
+       if (uMsg == WM_DEVICECHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)wParam, (DWORD)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define MSG_WM_COMMAND(func) \
+       if (uMsg == WM_COMMAND) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDisplayChange(UINT uBitsPerPixel, CSize sizeScreen)
+#define MSG_WM_DISPLAYCHANGE(func) \
+       if (uMsg == WM_DISPLAYCHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnEnterSizeMove()
+#define MSG_WM_ENTERSIZEMOVE(func) \
+       if (uMsg == WM_ENTERSIZEMOVE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnExitSizeMove()
+#define MSG_WM_EXITSIZEMOVE(func) \
+       if (uMsg == WM_EXITSIZEMOVE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HFONT OnGetFont()
+#define MSG_WM_GETFONT(func) \
+       if (uMsg == WM_GETFONT) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func(); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnGetHotKey()
+#define MSG_WM_GETHOTKEY(func) \
+       if (uMsg == WM_GETHOTKEY) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func(); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HICON OnGetIcon()
+#define MSG_WM_GETICON(func) \
+       if (uMsg == WM_GETICON) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)wParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnGetText(int cchTextMax, LPTSTR lpszText)
+#define MSG_WM_GETTEXT(func) \
+       if (uMsg == WM_GETTEXT) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((int)wParam, (LPTSTR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnGetTextLength()
+#define MSG_WM_GETTEXTLENGTH(func) \
+       if (uMsg == WM_GETTEXTLENGTH) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func(); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnHelp(LPHELPINFO lpHelpInfo)
+#define MSG_WM_HELP(func) \
+       if (uMsg == WM_HELP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((LPHELPINFO)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnHotKey(int nHotKeyID, UINT uModifiers, UINT uVirtKey)
+#define MSG_WM_HOTKEY(func) \
+       if (uMsg == WM_HOTKEY) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((int)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnInputLangChange(DWORD dwCharSet, HKL hKbdLayout)
+#define MSG_WM_INPUTLANGCHANGE(func) \
+       if (uMsg == WM_INPUTLANGCHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((DWORD)wParam, (HKL)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnInputLangChangeRequest(BOOL bSysCharSet, HKL hKbdLayout)
+#define MSG_WM_INPUTLANGCHANGEREQUEST(func) \
+       if (uMsg == WM_INPUTLANGCHANGEREQUEST) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)wParam, (HKL)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNextDlgCtl(BOOL bHandle, WPARAM wCtlFocus)
+#define MSG_WM_NEXTDLGCTL(func) \
+       if (uMsg == WM_NEXTDLGCTL) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)LOWORD(lParam), wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNextMenu(int nVirtKey, LPMDINEXTMENU lpMdiNextMenu)
+#define MSG_WM_NEXTMENU(func) \
+       if (uMsg == WM_NEXTMENU) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((int)wParam, (LPMDINEXTMENU)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnNotifyFormat(CWindow wndFrom, int nCommand)
+#define MSG_WM_NOTIFYFORMAT(func) \
+       if (uMsg == WM_NOTIFYFORMAT) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HWND)wParam, (int)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// BOOL OnPowerBroadcast(DWORD dwPowerEvent, DWORD dwData)
+#define MSG_WM_POWERBROADCAST(func) \
+       if (uMsg == WM_POWERBROADCAST) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((DWORD)wParam, (DWORD)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnPrint(CDCHandle dc, UINT uFlags)
+#define MSG_WM_PRINT(func) \
+       if (uMsg == WM_PRINT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HDC)wParam, (UINT)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnPrintClient(CDCHandle dc, UINT uFlags)
+#define MSG_WM_PRINTCLIENT(func) \
+       if (uMsg == WM_PRINTCLIENT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HDC)wParam, (UINT)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnRasDialEvent(RASCONNSTATE rasconnstate, DWORD dwError)
+#define MSG_WM_RASDIALEVENT(func) \
+       if (uMsg == WM_RASDIALEVENT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((RASCONNSTATE)wParam, (DWORD)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSetFont(CFont font, BOOL bRedraw)
+#define MSG_WM_SETFONT(func) \
+       if (uMsg == WM_SETFONT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((HFONT)wParam, (BOOL)LOWORD(lParam)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnSetHotKey(int nVirtKey, UINT uFlags)
+#define MSG_WM_SETHOTKEY(func) \
+       if (uMsg == WM_SETHOTKEY) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((int)LOBYTE(LOWORD(wParam)), (UINT)HIBYTE(LOWORD(wParam))); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HICON OnSetIcon(UINT uType, HICON hIcon)
+#define MSG_WM_SETICON(func) \
+       if (uMsg == WM_SETICON) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)wParam, (HICON)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnSetRedraw(BOOL bRedraw)
+#define MSG_WM_SETREDRAW(func) \
+       if (uMsg == WM_SETREDRAW) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((BOOL)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnSetText(LPCTSTR lpstrText)
+#define MSG_WM_SETTEXT(func) \
+       if (uMsg == WM_SETTEXT) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((LPCTSTR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnUserChanged()
+#define MSG_WM_USERCHANGED(func) \
+       if (uMsg == WM_USERCHANGED) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+///////////////////////////////////////////////////////////////////////////////
+// New NT4 & NT5 messages
+
+#if(_WIN32_WINNT >= 0x0400)
+
+// void OnMouseHover(WPARAM wParam, CPoint ptPos)
+#define MSG_WM_MOUSEHOVER(func) \
+       if (uMsg == WM_MOUSEHOVER) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMouseLeave()
+#define MSG_WM_MOUSELEAVE(func) \
+       if (uMsg == WM_MOUSELEAVE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+#endif /* _WIN32_WINNT >= 0x0400 */
+
+#if(WINVER >= 0x0500)
+
+// void OnMenuRButtonUp(WPARAM wParam, CMenu menu)
+#define MSG_WM_MENURBUTTONUP(func) \
+       if (uMsg == WM_MENURBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(wParam, (HMENU)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnMenuDrag(WPARAM wParam, CMenu menu)
+#define MSG_WM_MENUDRAG(func) \
+       if (uMsg == WM_MENUDRAG) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func(wParam, (HMENU)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnMenuGetObject(PMENUGETOBJECTINFO info)
+#define MSG_WM_MENUGETOBJECT(func) \
+       if (uMsg == WM_MENUGETOBJECT) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((PMENUGETOBJECTINFO)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnUnInitMenuPopup(UINT nID, CMenu menu)
+#define MSG_WM_UNINITMENUPOPUP(func) \
+       if (uMsg == WM_UNINITMENUPOPUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(lParam), (HMENU)wParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnMenuCommand(WPARAM nIndex, CMenu menu)
+#define MSG_WM_MENUCOMMAND(func) \
+       if (uMsg == WM_MENUCOMMAND) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(wParam, (HMENU)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+#endif /* WINVER >= 0x0500 */
+
+#if(_WIN32_WINNT >= 0x0500)
+
+// BOOL OnAppCommand(CWindow wndFocus, short cmd, WORD uDevice, int dwKeys)
+#define MSG_WM_APPCOMMAND(func) \
+       if (uMsg == WM_APPCOMMAND) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HWND)wParam, GET_APPCOMMAND_LPARAM(lParam), GET_DEVICE_LPARAM(lParam), GET_KEYSTATE_LPARAM(lParam)); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNCXButtonDown(int fwButton, short nHittest, CPoint ptPos)
+#define MSG_WM_NCXBUTTONDOWN(func) \
+       if (uMsg == WM_NCXBUTTONDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNCXButtonUp(int fwButton, short nHittest, CPoint ptPos)
+#define MSG_WM_NCXBUTTONUP(func) \
+       if (uMsg == WM_NCXBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnNCXButtonDblClk(int fwButton, short nHittest, CPoint ptPos)
+#define MSG_WM_NCXBUTTONDBLCLK(func) \
+       if (uMsg == WM_NCXBUTTONDBLCLK) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnXButtonDown(int fwButton, int dwKeys, CPoint ptPos)
+#define MSG_WM_XBUTTONDOWN(func) \
+       if (uMsg == WM_XBUTTONDOWN) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnXButtonUp(int fwButton, int dwKeys, CPoint ptPos)
+#define MSG_WM_XBUTTONUP(func) \
+       if (uMsg == WM_XBUTTONUP) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnXButtonDblClk(int fwButton, int dwKeys, CPoint ptPos)
+#define MSG_WM_XBUTTONDBLCLK(func) \
+       if (uMsg == WM_XBUTTONDBLCLK) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnChangeUIState(WORD nAction, WORD nState)
+#define MSG_WM_CHANGEUISTATE(func) \
+       if (uMsg == WM_CHANGEUISTATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(LOWORD(wParam), HIWORD(wParam)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnUpdateUIState(WORD nAction, WORD nState)
+#define MSG_WM_UPDATEUISTATE(func) \
+       if (uMsg == WM_UPDATEUISTATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(LOWORD(wParam), HIWORD(wParam)); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnQueryUIState()
+#define MSG_WM_QUERYUISTATE(func) \
+       if (uMsg == WM_QUERYUISTATE) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func(); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+#endif // (_WIN32_WINNT >= 0x0500)
+
+#if(_WIN32_WINNT >= 0x0501)
+
+// void OnInput(WPARAM RawInputCode, HRAWINPUT hRawInput)
+#define MSG_WM_INPUT(func) \
+       if (uMsg == WM_INPUT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(GET_RAWINPUT_CODE_WPARAM(wParam), (HRAWINPUT)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnUniChar(TCHAR nChar, UINT nRepCnt, UINT nFlags)
+#define MSG_WM_UNICHAR(func) \
+       if (uMsg == WM_UNICHAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
+               if(IsMsgHandled()) \
+               { \
+                       lResult = (wParam == UNICODE_NOCHAR) ? TRUE : FALSE; \
+                       return TRUE; \
+               } \
+       }
+
+// void OnWTSSessionChange(WPARAM nStatusCode, PWTSSESSION_NOTIFICATION nSessionID)
+#define MSG_WM_WTSSESSION_CHANGE(func) \
+       if (uMsg == WM_WTSSESSION_CHANGE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(wParam, (PWTSSESSION_NOTIFICATION)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// OnThemeChanged()
+#define MSG_WM_THEMECHANGED(func) \
+       if (uMsg == WM_THEMECHANGED) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+#endif /* _WIN32_WINNT >= 0x0501 */
+
+///////////////////////////////////////////////////////////////////////////////
+// ATL defined messages
+
+// BOOL OnForwardMsg(LPMSG Msg, DWORD nUserData)
+#define MSG_WM_FORWARDMSG(func) \
+       if (uMsg == WM_FORWARDMSG) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((LPMSG)lParam, (DWORD)wParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+///////////////////////////////////////////////////////////////////////////////
+// Dialog specific messages
+
+// LRESULT OnDMGetDefID()
+#define MSG_DM_GETDEFID(func) \
+       if (uMsg == DM_GETDEFID) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func(); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDMSetDefID(UINT DefID)
+#define MSG_DM_SETDEFID(func) \
+       if (uMsg == DM_SETDEFID) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnDMReposition()
+#define MSG_DM_REPOSITION(func) \
+       if (uMsg == DM_REPOSITION) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+///////////////////////////////////////////////////////////////////////////////
+// Reflected messages
+
+// void OnReflectedCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define MSG_OCM_COMMAND(func) \
+       if (uMsg == OCM_COMMAND) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedNotify(int idCtrl, LPNMHDR pnmh)
+#define MSG_OCM_NOTIFY(func) \
+       if (uMsg == OCM_NOTIFY) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((int)wParam, (LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnReflectedParentNotify(UINT message, UINT nChildID, LPARAM lParam)
+#define MSG_OCM_PARENTNOTIFY(func) \
+       if (uMsg == OCM_PARENTNOTIFY) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnReflectedDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
+#define MSG_OCM_DRAWITEM(func) \
+       if (uMsg == OCM_DRAWITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnReflectedMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
+#define MSG_OCM_MEASUREITEM(func) \
+       if (uMsg == OCM_MEASUREITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnReflectedCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
+#define MSG_OCM_COMPAREITEM(func) \
+       if (uMsg == OCM_COMPAREITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnReflectedDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct)
+#define MSG_OCM_DELETEITEM(func) \
+       if (uMsg == OCM_DELETEITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \
+               lResult = TRUE; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// int OnReflectedVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox)
+#define MSG_OCM_VKEYTOITEM(func) \
+       if (uMsg == OCM_VKEYTOITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+//int OnReflectedCharToItem(UINT nChar, UINT nIndex, CListBox listBox)
+#define MSG_OCM_CHARTOITEM(func) \
+       if (uMsg == OCM_CHARTOITEM) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnReflectedHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
+#define MSG_OCM_HSCROLL(func) \
+       if (uMsg == OCM_HSCROLL) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnReflectedVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
+#define MSG_OCM_VSCROLL(func) \
+       if (uMsg == OCM_VSCROLL) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnReflectedCtlColorEdit(CDCHandle dc, CEdit edit)
+#define MSG_OCM_CTLCOLOREDIT(func) \
+       if (uMsg == OCM_CTLCOLOREDIT) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnReflectedCtlColorListBox(CDCHandle dc, CListBox listBox)
+#define MSG_OCM_CTLCOLORLISTBOX(func) \
+       if (uMsg == OCM_CTLCOLORLISTBOX) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnReflectedCtlColorBtn(CDCHandle dc, CButton button)
+#define MSG_OCM_CTLCOLORBTN(func) \
+       if (uMsg == OCM_CTLCOLORBTN) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnReflectedCtlColorDlg(CDCHandle dc, CWindow wnd)
+#define MSG_OCM_CTLCOLORDLG(func) \
+       if (uMsg == OCM_CTLCOLORDLG) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnReflectedCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar)
+#define MSG_OCM_CTLCOLORSCROLLBAR(func) \
+       if (uMsg == OCM_CTLCOLORSCROLLBAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// HBRUSH OnReflectedCtlColorStatic(CDCHandle dc, CStatic wndStatic)
+#define MSG_OCM_CTLCOLORSTATIC(func) \
+       if (uMsg == OCM_CTLCOLORSTATIC) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+///////////////////////////////////////////////////////////////////////////////
+// Edit specific messages
+
+// void OnClear()
+#define MSG_WM_CLEAR(func) \
+       if (uMsg == WM_CLEAR) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCopy()
+#define MSG_WM_COPY(func) \
+       if (uMsg == WM_COPY) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCut()
+#define MSG_WM_CUT(func) \
+       if (uMsg == WM_CUT) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnPaste()
+#define MSG_WM_PASTE(func) \
+       if (uMsg == WM_PASTE) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnUndo()
+#define MSG_WM_UNDO(func) \
+       if (uMsg == WM_UNDO) \
+       { \
+               SetMsgHandled(TRUE); \
+               func(); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+///////////////////////////////////////////////////////////////////////////////
+// Generic message handlers
+
+// LRESULT OnMessageHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam)
+#define MESSAGE_HANDLER_EX(msg, func) \
+       if(uMsg == msg) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func(uMsg, wParam, lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnMessageRangeHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam)
+#define MESSAGE_RANGE_HANDLER_EX(msgFirst, msgLast, func) \
+       if(uMsg >= msgFirst && uMsg <= msgLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func(uMsg, wParam, lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+///////////////////////////////////////////////////////////////////////////////
+// Commands and notifications
+
+// void OnCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define COMMAND_HANDLER_EX(id, code, func) \
+       if (uMsg == WM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define COMMAND_ID_HANDLER_EX(id, func) \
+       if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define COMMAND_CODE_HANDLER_EX(code, func) \
+       if (uMsg == WM_COMMAND && code == HIWORD(wParam)) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnNotifyHandlerEX(LPNMHDR pnmh)
+#define NOTIFY_HANDLER_EX(id, cd, func) \
+       if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnNotifyIDHandlerEX(LPNMHDR pnmh)
+#define NOTIFY_ID_HANDLER_EX(id, func) \
+       if (uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnNotifyCodeHandlerEX(LPNMHDR pnmh)
+#define NOTIFY_CODE_HANDLER_EX(cd, func) \
+       if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \
+       if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \
+       if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnNotifyRangeHandlerEX(LPNMHDR pnmh)
+#define NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \
+       if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnNotifyRangeCodeHandlerEX(LPNMHDR pnmh)
+#define NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \
+       if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define REFLECTED_COMMAND_HANDLER_EX(id, code, func) \
+       if (uMsg == OCM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define REFLECTED_COMMAND_ID_HANDLER_EX(id, func) \
+       if (uMsg == OCM_COMMAND && id == LOWORD(wParam)) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define REFLECTED_COMMAND_CODE_HANDLER_EX(code, func) \
+       if (uMsg == OCM_COMMAND && code == HIWORD(wParam)) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedNotifyHandlerEX(LPNMHDR pnmh)
+#define REFLECTED_NOTIFY_HANDLER_EX(id, cd, func) \
+       if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedNotifyIDHandlerEX(LPNMHDR pnmh)
+#define REFLECTED_NOTIFY_ID_HANDLER_EX(id, func) \
+       if (uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedNotifyCodeHandlerEX(LPNMHDR pnmh)
+#define REFLECTED_NOTIFY_CODE_HANDLER_EX(cd, func) \
+       if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnReflectedCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define REFLECTED_COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \
+       if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// void OnReflectedCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define REFLECTED_COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \
+       if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+               lResult = 0; \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedNotifyRangeHandlerEX(LPNMHDR pnmh)
+#define REFLECTED_NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \
+       if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+// LRESULT OnReflectedNotifyRangeCodeHandlerEX(LPNMHDR pnmh)
+#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \
+       if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
+       { \
+               SetMsgHandled(TRUE); \
+               lResult = func((LPNMHDR)lParam); \
+               if(IsMsgHandled()) \
+                       return TRUE; \
+       }
+
+#endif // __ATLCRACK_H__
diff --git a/include/WTL/Include/atlctrls.h b/include/WTL/Include/atlctrls.h
new file mode 100644 (file)
index 0000000..7aa9254
--- /dev/null
@@ -0,0 +1,10039 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLCTRLS_H__
+#define __ATLCTRLS_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlctrls.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atlctrls.h requires atlwin.h to be included first
+#endif
+
+#if (_WIN32_IE < 0x0300)
+       #error atlctrls.h requires IE Version 3.0 or higher
+#endif
+
+#ifndef _WIN32_WCE
+  #include <richedit.h>
+  #include <richole.h>
+#elif defined(WIN32_PLATFORM_WFSP) && !defined(_WINUSERM_H_)
+  #include <winuserm.h>
+#endif // !_WIN32_WCE
+
+// protect template members from windowsx.h macros
+#ifdef _INC_WINDOWSX
+  #undef GetNextSibling
+  #undef GetPrevSibling
+#endif // _INC_WINDOWSX
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CStaticT<TBase> - CStatic
+// CButtonT<TBase> - CButton
+// CListBoxT<TBase> - CListBox
+// CComboBoxT<TBase> - CComboBox
+// CEditT<TBase> - CEdit
+// CEditCommands<T>
+// CScrollBarT<TBase> - CScrollBar
+//
+// CImageList
+// CListViewCtrlT<TBase> - CListViewCtrl
+// CTreeViewCtrlT<TBase> - CTreeViewCtrl
+// CTreeItemT<TBase> - CTreeItem
+// CTreeViewCtrlExT<TBase> - CTreeViewCtrlEx
+// CHeaderCtrlT<TBase> - CHeaderCtrl
+// CToolBarCtrlT<TBase> - CToolBarCtrl
+// CStatusBarCtrlT<TBase> - CStatusBarCtrl
+// CTabCtrlT<TBase> - CTabCtrl
+// CToolInfo
+// CToolTipCtrlT<TBase> - CToolTipCtrl
+// CTrackBarCtrlT<TBase> - CTrackBarCtrl
+// CUpDownCtrlT<TBase> - CUpDownCtrl
+// CProgressBarCtrlT<TBase> - CProgressBarCtrl
+// CHotKeyCtrlT<TBase> - CHotKeyCtrl
+// CAnimateCtrlT<TBase> - CAnimateCtrl
+// CRichEditCtrlT<TBase> - CRichEditCtrl
+// CRichEditCommands<T>
+// CDragListBoxT<TBase> - CDragListBox
+// CDragListNotifyImpl<T>
+// CReBarCtrlT<TBase> - CReBarCtrl
+// CComboBoxExT<TBase> - CComboBoxEx
+// CDateTimePickerCtrlT<TBase> - CDateTimePickerCtrl
+// CMonthCalendarCtrlT<TBase> - CMonthCalendarCtrl
+// CFlatScrollBarImpl<T>
+// CFlatScrollBarT<TBase> - CFlatScrollBar
+// CIPAddressCtrlT<TBase> - CIPAddressCtrl
+// CPagerCtrlT<TBase> - CPagerCtrl
+// CLinkCtrlT<TBase> - CLinkCtrl
+//
+// CCustomDraw<T>
+//
+// CCECommandBarCtrlT<TBase> - CCECommandBarCtrl
+// CCECommandBandsCtrlT<TBase> - CCECommandBandsCtrl
+
+
+namespace WTL
+{
+
+// These are wrapper classes for Windows standard and common controls.
+// To implement a window based on a control, use following:
+// Example: Implementing a window based on a list box
+//
+// class CMyListBox : CWindowImpl<CMyListBox, CListBox>
+// {
+// public:
+//      BEGIN_MSG_MAP(CMyListBox)
+//          // put your message handler entries here
+//      END_MSG_MAP()
+// };
+
+
+
+// --- Standard Windows controls ---
+
+///////////////////////////////////////////////////////////////////////////////
+// CStatic - client side for a Windows STATIC control
+
+template <class TBase>
+class CStaticT : public TBase
+{
+public:
+// Constructors
+       CStaticT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CStaticT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return _T("STATIC");
+       }
+
+#ifndef _WIN32_WCE
+       HICON GetIcon() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HICON)::SendMessage(m_hWnd, STM_GETICON, 0, 0L);
+       }
+
+       HICON SetIcon(HICON hIcon)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HICON)::SendMessage(m_hWnd, STM_SETICON, (WPARAM)hIcon, 0L);
+       }
+
+       HENHMETAFILE GetEnhMetaFile() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HENHMETAFILE)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ENHMETAFILE, 0L);
+       }
+
+       HENHMETAFILE SetEnhMetaFile(HENHMETAFILE hMetaFile)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HENHMETAFILE)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)hMetaFile);
+       }
+#else // CE specific
+       HICON GetIcon() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HICON)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ICON, 0L);
+       }
+
+       HICON SetIcon(HICON hIcon)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HICON)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+       }
+#endif // _WIN32_WCE
+
+       CBitmapHandle GetBitmap() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_BITMAP, 0L));
+       }
+
+       CBitmapHandle SetBitmap(HBITMAP hBitmap)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap));
+       }
+
+       HCURSOR GetCursor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HCURSOR)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_CURSOR, 0L);
+       }
+
+       HCURSOR SetCursor(HCURSOR hCursor)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HCURSOR)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor);
+       }
+};
+
+typedef CStaticT<ATL::CWindow>   CStatic;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CButton - client side for a Windows BUTTON control
+
+template <class TBase>
+class CButtonT : public TBase
+{
+public:
+// Constructors
+       CButtonT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CButtonT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return _T("BUTTON");
+       }
+
+       UINT GetState() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, BM_GETSTATE, 0, 0L);
+       }
+
+       void SetState(BOOL bHighlight)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, BM_SETSTATE, bHighlight, 0L);
+       }
+
+       int GetCheck() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, BM_GETCHECK, 0, 0L);
+       }
+
+       void SetCheck(int nCheck)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, BM_SETCHECK, nCheck, 0L);
+       }
+
+       UINT GetButtonStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::GetWindowLong(m_hWnd, GWL_STYLE) & 0xFFFF;
+       }
+
+       void SetButtonStyle(UINT nStyle, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, BM_SETSTYLE, nStyle, (LPARAM)bRedraw);
+       }
+
+#ifndef _WIN32_WCE
+       HICON GetIcon() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HICON)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_ICON, 0L);
+       }
+
+       HICON SetIcon(HICON hIcon)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HICON)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+       }
+
+       CBitmapHandle GetBitmap() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0L));
+       }
+
+       CBitmapHandle SetBitmap(HBITMAP hBitmap)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap));
+       }
+#endif // !_WIN32_WCE
+
+#if (_WIN32_WINNT >= 0x0501)
+       BOOL GetIdealSize(LPSIZE lpSize) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, BCM_GETIDEALSIZE, 0, (LPARAM)lpSize);
+       }
+
+       BOOL GetImageList(PBUTTON_IMAGELIST pButtonImagelist) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, BCM_GETIMAGELIST, 0, (LPARAM)pButtonImagelist);
+       }
+
+       BOOL SetImageList(PBUTTON_IMAGELIST pButtonImagelist)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, BCM_SETIMAGELIST, 0, (LPARAM)pButtonImagelist);
+       }
+
+       BOOL GetTextMargin(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, BCM_GETTEXTMARGIN, 0, (LPARAM)lpRect);
+       }
+
+       BOOL SetTextMargin(LPRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, BCM_SETTEXTMARGIN, 0, (LPARAM)lpRect);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+#if (WINVER >= 0x0600)
+       void SetDontClick(BOOL bDontClick)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, BM_SETDONTCLICK, (WPARAM)bDontClick, 0L);
+       }
+#endif // (WINVER >= 0x0600)
+
+#if (_WIN32_WINNT >= 0x0600)
+       BOOL SetDropDownState(BOOL bDropDown)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
+               return (BOOL)::SendMessage(m_hWnd, BCM_SETDROPDOWNSTATE, (WPARAM)bDropDown, 0L);
+       }
+
+       BOOL GetSplitInfo(PBUTTON_SPLITINFO pSplitInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
+               return (BOOL)::SendMessage(m_hWnd, BCM_GETSPLITINFO, 0, (LPARAM)pSplitInfo);
+       }
+
+       BOOL SetSplitInfo(PBUTTON_SPLITINFO pSplitInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
+               return (BOOL)::SendMessage(m_hWnd, BCM_SETSPLITINFO, 0, (LPARAM)pSplitInfo);
+       }
+
+       int GetNoteLength() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
+               return (int)::SendMessage(m_hWnd, BCM_GETNOTELENGTH, 0, 0L);
+       }
+
+       BOOL GetNote(LPWSTR lpstrNoteText, int cchNoteText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
+               return (BOOL)::SendMessage(m_hWnd, BCM_GETNOTE, cchNoteText, (LPARAM)lpstrNoteText);
+       }
+
+       BOOL SetNote(LPCWSTR lpstrNoteText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
+               return (BOOL)::SendMessage(m_hWnd, BCM_SETNOTE, 0, (LPARAM)lpstrNoteText);
+       }
+
+       LRESULT SetElevationRequiredState(BOOL bSet)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SendMessage(m_hWnd, BCM_SETSHIELD, 0, (LPARAM)bSet);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+// Operations
+       void Click()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, BM_CLICK, 0, 0L);
+       }
+};
+
+typedef CButtonT<ATL::CWindow>   CButton;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CListBox - client side for a Windows LISTBOX control
+
+template <class TBase>
+class CListBoxT : public TBase
+{
+public:
+// Constructors
+       CListBoxT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CListBoxT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return _T("LISTBOX");
+       }
+
+       // for entire listbox
+       int GetCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETCOUNT, 0, 0L);
+       }
+
+#ifndef _WIN32_WCE
+       int SetCount(int cItems)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(((GetStyle() & LBS_NODATA) != 0) && ((GetStyle() & LBS_HASSTRINGS) == 0));
+               return (int)::SendMessage(m_hWnd, LB_SETCOUNT, cItems, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       int GetHorizontalExtent() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETHORIZONTALEXTENT, 0, 0L);
+       }
+
+       void SetHorizontalExtent(int cxExtent)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LB_SETHORIZONTALEXTENT, cxExtent, 0L);
+       }
+
+       int GetTopIndex() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETTOPINDEX, 0, 0L);
+       }
+
+       int SetTopIndex(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_SETTOPINDEX, nIndex, 0L);
+       }
+
+       LCID GetLocale() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LCID)::SendMessage(m_hWnd, LB_GETLOCALE, 0, 0L);
+       }
+
+       LCID SetLocale(LCID nNewLocale)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LCID)::SendMessage(m_hWnd, LB_SETLOCALE, (WPARAM)nNewLocale, 0L);
+       }
+
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+       DWORD GetListBoxInfo() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+#if (_WIN32_WINNT >= 0x0501)
+               return (DWORD)::SendMessage(m_hWnd, LB_GETLISTBOXINFO, 0, 0L);
+#else // !(_WIN32_WINNT >= 0x0501)
+               return ::GetListBoxInfo(m_hWnd);
+#endif // !(_WIN32_WINNT >= 0x0501)
+       }
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+
+       // for single-selection listboxes
+       int GetCurSel() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
+               return (int)::SendMessage(m_hWnd, LB_GETCURSEL, 0, 0L);
+       }
+
+       int SetCurSel(int nSelect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
+               return (int)::SendMessage(m_hWnd, LB_SETCURSEL, nSelect, 0L);
+       }
+
+       // for multiple-selection listboxes
+       int GetSel(int nIndex) const           // also works for single-selection
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETSEL, nIndex, 0L);
+       }
+
+       int SetSel(int nIndex, BOOL bSelect = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
+               return (int)::SendMessage(m_hWnd, LB_SETSEL, bSelect, nIndex);
+       }
+
+       int GetSelCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
+               return (int)::SendMessage(m_hWnd, LB_GETSELCOUNT, 0, 0L);
+       }
+
+       int GetSelItems(int nMaxItems, LPINT rgIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
+               return (int)::SendMessage(m_hWnd, LB_GETSELITEMS, nMaxItems, (LPARAM)rgIndex);
+       }
+
+       int GetAnchorIndex() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
+               return (int)::SendMessage(m_hWnd, LB_GETANCHORINDEX, 0, 0L);
+       }
+
+       void SetAnchorIndex(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
+               ::SendMessage(m_hWnd, LB_SETANCHORINDEX, nIndex, 0L);
+       }
+
+       int GetCaretIndex() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETCARETINDEX, 0, 0);
+       }
+
+       int SetCaretIndex(int nIndex, BOOL bScroll = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_SETCARETINDEX, nIndex, MAKELONG(bScroll, 0));
+       }
+
+       // for listbox items
+       DWORD_PTR GetItemData(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD_PTR)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L);
+       }
+
+       int SetItemData(int nIndex, DWORD_PTR dwItemData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
+       }
+
+       void* GetItemDataPtr(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (void*)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L);
+       }
+
+       int SetItemDataPtr(int nIndex, void* pData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItemData(nIndex, (DWORD_PTR)pData);
+       }
+
+       int GetItemRect(int nIndex, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect);
+       }
+
+       int GetText(int nIndex, LPTSTR lpszBuffer) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETTEXT, nIndex, (LPARAM)lpszBuffer);
+       }
+
+#ifndef _ATL_NO_COM
+#ifdef _OLEAUTO_H_
+       BOOL GetTextBSTR(int nIndex, BSTR& bstrText) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(bstrText == NULL);
+
+               int nLen = GetTextLen(nIndex);
+               if(nLen == LB_ERR)
+                       return FALSE;
+
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpstrText = buff.Allocate(nLen + 1);
+               if(lpstrText == NULL)
+                       return FALSE;
+
+               if(GetText(nIndex, lpstrText) == LB_ERR)
+                       return FALSE;
+
+               bstrText = ::SysAllocString(T2OLE(lpstrText));
+               return (bstrText != NULL) ? TRUE : FALSE;
+       }
+#endif // _OLEAUTO_H_
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       int GetText(int nIndex, _CSTRING_NS::CString& strText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int cchLen = GetTextLen(nIndex);
+               if(cchLen == LB_ERR)
+                       return LB_ERR;
+               int nRet = LB_ERR;
+               LPTSTR lpstr = strText.GetBufferSetLength(cchLen);
+               if(lpstr != NULL)
+               {
+                       nRet = GetText(nIndex, lpstr);
+                       strText.ReleaseBuffer();
+               }
+               return nRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       int GetTextLen(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETTEXTLEN, nIndex, 0L);
+       }
+
+       int GetItemHeight(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_GETITEMHEIGHT, nIndex, 0L);
+       }
+
+       int SetItemHeight(int nIndex, UINT cyItemHeight)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
+       }
+
+       // Settable only attributes
+       void SetColumnWidth(int cxWidth)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LB_SETCOLUMNWIDTH, cxWidth, 0L);
+       }
+
+       BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
+               return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
+       }
+
+       BOOL SetTabStops()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
+               return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 0, 0L);
+       }
+
+       BOOL SetTabStops(const int& cxEachStop)    // takes an 'int'
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
+               return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
+       }
+
+// Operations
+       int InitStorage(int nItems, UINT nBytes)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_INITSTORAGE, (WPARAM)nItems, nBytes);
+       }
+
+       void ResetContent()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LB_RESETCONTENT, 0, 0L);
+       }
+
+       UINT ItemFromPoint(POINT pt, BOOL& bOutside) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dw = (DWORD)::SendMessage(m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
+               bOutside = (BOOL)HIWORD(dw);
+               return (UINT)LOWORD(dw);
+       }
+
+       // manipulating listbox items
+       int AddString(LPCTSTR lpszItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem);
+       }
+
+       int DeleteString(UINT nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_DELETESTRING, nIndex, 0L);
+       }
+
+       int InsertString(int nIndex, LPCTSTR lpszItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_INSERTSTRING, nIndex, (LPARAM)lpszItem);
+       }
+
+#ifndef _WIN32_WCE
+       int Dir(UINT attr, LPCTSTR lpszWildCard)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_DIR, attr, (LPARAM)lpszWildCard);
+       }
+
+       int AddFile(LPCTSTR lpstrFileName)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_ADDFILE, 0, (LPARAM)lpstrFileName);
+       }
+#endif // !_WIN32_WCE
+
+       // selection helpers
+       int FindString(int nStartAfter, LPCTSTR lpszItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_FINDSTRING, nStartAfter, (LPARAM)lpszItem);
+       }
+
+       int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
+       }
+
+       int SelectString(int nStartAfter, LPCTSTR lpszItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LB_SELECTSTRING, nStartAfter, (LPARAM)lpszItem);
+       }
+
+       int SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
+               ATLASSERT(nFirstItem <= nLastItem);
+               return bSelect ? (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nFirstItem, nLastItem) : (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nLastItem, nFirstItem);
+       }
+
+#ifdef WIN32_PLATFORM_WFSP   // SmartPhone only messages
+       DWORD GetInputMode(BOOL bCurrentMode = TRUE)
+       {
+               return SendMessage(LB_GETINPUTMODE, 0, (LPARAM)bCurrentMode);
+       }
+
+       BOOL SetInputMode(DWORD dwMode)
+       {
+               return SendMessage(LB_SETINPUTMODE, 0, (LPARAM)dwMode);
+       }
+#endif // WIN32_PLATFORM_WFSP
+};
+
+typedef CListBoxT<ATL::CWindow>   CListBox;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CComboBox - client side for a Windows COMBOBOX control
+
+#ifndef WIN32_PLATFORM_WFSP   // No COMBOBOX on SmartPhones
+
+template <class TBase>
+class CComboBoxT : public TBase
+{
+public:
+// Constructors
+       CComboBoxT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CComboBoxT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return _T("COMBOBOX");
+       }
+
+       // for entire combo box
+       int GetCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0L);
+       }
+
+       int GetCurSel() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0L);
+       }
+
+       int SetCurSel(int nSelect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_SETCURSEL, nSelect, 0L);
+       }
+
+       LCID GetLocale() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LCID)::SendMessage(m_hWnd, CB_GETLOCALE, 0, 0L);
+       }
+
+       LCID SetLocale(LCID nNewLocale)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LCID)::SendMessage(m_hWnd, CB_SETLOCALE, (WPARAM)nNewLocale, 0L);
+       }
+
+       int GetTopIndex() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_GETTOPINDEX, 0, 0L);
+       }
+
+       int SetTopIndex(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_SETTOPINDEX, nIndex, 0L);
+       }
+
+       UINT GetHorizontalExtent() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, CB_GETHORIZONTALEXTENT, 0, 0L);
+       }
+
+       void SetHorizontalExtent(UINT nExtent)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, CB_SETHORIZONTALEXTENT, nExtent, 0L);
+       }
+
+       int GetDroppedWidth() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_GETDROPPEDWIDTH, 0, 0L);
+       }
+
+       int SetDroppedWidth(UINT nWidth)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_SETDROPPEDWIDTH, nWidth, 0L);
+       }
+
+#if ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
+       BOOL GetComboBoxInfo(PCOMBOBOXINFO pComboBoxInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+#if ((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
+               return (BOOL)::SendMessage(m_hWnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)pComboBoxInfo);
+#else // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
+               return ::GetComboBoxInfo(m_hWnd, pComboBoxInfo);
+#endif // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
+       }
+#endif // ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
+
+       // for edit control
+       DWORD GetEditSel() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, CB_GETEDITSEL, 0, 0L);
+       }
+
+       BOOL SetEditSel(int nStartChar, int nEndChar)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CB_SETEDITSEL, 0, MAKELONG(nStartChar, nEndChar));
+       }
+
+       // for combobox item
+       DWORD_PTR GetItemData(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD_PTR)::SendMessage(m_hWnd, CB_GETITEMDATA, nIndex, 0L);
+       }
+
+       int SetItemData(int nIndex, DWORD_PTR dwItemData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
+       }
+
+       void* GetItemDataPtr(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (void*)GetItemData(nIndex);
+       }
+
+       int SetItemDataPtr(int nIndex, void* pData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItemData(nIndex, (DWORD_PTR)pData);
+       }
+
+       int GetLBText(int nIndex, LPTSTR lpszText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_GETLBTEXT, nIndex, (LPARAM)lpszText);
+       }
+
+#ifndef _ATL_NO_COM
+       BOOL GetLBTextBSTR(int nIndex, BSTR& bstrText) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(bstrText == NULL);
+
+               int nLen = GetLBTextLen(nIndex);
+               if(nLen == CB_ERR)
+                       return FALSE;
+
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpstrText = buff.Allocate(nLen + 1);
+               if(lpstrText == NULL)
+                       return FALSE;
+
+               if(GetLBText(nIndex, lpstrText) == CB_ERR)
+                       return FALSE;
+
+               bstrText = ::SysAllocString(T2OLE(lpstrText));
+               return (bstrText != NULL) ? TRUE : FALSE;
+       }
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       int GetLBText(int nIndex, _CSTRING_NS::CString& strText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int cchLen = GetLBTextLen(nIndex);
+               if(cchLen == CB_ERR)
+                       return CB_ERR;
+               int nRet = CB_ERR;
+               LPTSTR lpstr = strText.GetBufferSetLength(cchLen);
+               if(lpstr != NULL)
+               {
+                       nRet = GetLBText(nIndex, lpstr);
+                       strText.ReleaseBuffer();
+               }
+               return nRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       int GetLBTextLen(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_GETLBTEXTLEN, nIndex, 0L);
+       }
+
+       int GetItemHeight(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_GETITEMHEIGHT, nIndex, 0L);
+       }
+
+       int SetItemHeight(int nIndex, UINT cyItemHeight)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
+       }
+
+       BOOL GetExtendedUI() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CB_GETEXTENDEDUI, 0, 0L);
+       }
+
+       int SetExtendedUI(BOOL bExtended = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_SETEXTENDEDUI, bExtended, 0L);
+       }
+
+       void GetDroppedControlRect(LPRECT lprect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)lprect);
+       }
+
+       BOOL GetDroppedState() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CB_GETDROPPEDSTATE, 0, 0L);
+       }
+
+#if (_WIN32_WINNT >= 0x0501)
+       int GetMinVisible() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_GETMINVISIBLE, 0, 0L);
+       }
+
+       BOOL SetMinVisible(int nMinVisible)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CB_SETMINVISIBLE, nMinVisible, 0L);
+       }
+
+       // Vista only
+       BOOL GetCueBannerText(LPWSTR lpwText, int cchText) const
+       {
+#ifndef CB_GETCUEBANNER
+               const UINT CB_GETCUEBANNER = (CBM_FIRST + 4);
+#endif
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CB_GETCUEBANNER, (WPARAM)lpwText, cchText);
+       }
+
+       // Vista only
+       BOOL SetCueBannerText(LPCWSTR lpcwText)
+       {
+#ifndef CB_SETCUEBANNER
+               const UINT CB_SETCUEBANNER = (CBM_FIRST + 3);
+#endif
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CB_SETCUEBANNER, 0, (LPARAM)lpcwText);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+// Operations
+       int InitStorage(int nItems, UINT nBytes)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_INITSTORAGE, (WPARAM)nItems, nBytes);
+       }
+
+       void ResetContent()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0L);
+       }
+
+       // for edit control
+       BOOL LimitText(int nMaxChars)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CB_LIMITTEXT, nMaxChars, 0L);
+       }
+
+       // for drop-down combo boxes
+       void ShowDropDown(BOOL bShowIt = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, CB_SHOWDROPDOWN, bShowIt, 0L);
+       }
+
+       // manipulating listbox items
+       int AddString(LPCTSTR lpszString)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_ADDSTRING, 0, (LPARAM)lpszString);
+       }
+
+       int DeleteString(UINT nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_DELETESTRING, nIndex, 0L);
+       }
+
+       int InsertString(int nIndex, LPCTSTR lpszString)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_INSERTSTRING, nIndex, (LPARAM)lpszString);
+       }
+
+#ifndef _WIN32_WCE
+       int Dir(UINT attr, LPCTSTR lpszWildCard)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_DIR, attr, (LPARAM)lpszWildCard);
+       }
+#endif // !_WIN32_WCE
+
+       // selection helpers
+       int FindString(int nStartAfter, LPCTSTR lpszString) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_FINDSTRING, nStartAfter, (LPARAM)lpszString);
+       }
+
+       int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
+       }
+
+       int SelectString(int nStartAfter, LPCTSTR lpszString)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CB_SELECTSTRING, nStartAfter, (LPARAM)lpszString);
+       }
+
+       // Clipboard operations
+       void Clear()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
+       }
+
+       void Copy()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_COPY, 0, 0L);
+       }
+
+       void Cut()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_CUT, 0, 0L);
+       }
+
+       void Paste()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
+       }
+};
+
+typedef CComboBoxT<ATL::CWindow>   CComboBox;
+
+#endif // !WIN32_PLATFORM_WFSP
+
+///////////////////////////////////////////////////////////////////////////////
+// CEdit - client side for a Windows EDIT control
+
+template <class TBase>
+class CEditT : public TBase
+{
+public:
+// Constructors
+       CEditT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CEditT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return _T("EDIT");
+       }
+
+       BOOL CanUndo() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L);
+       }
+
+       int GetLineCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L);
+       }
+
+       BOOL GetModify() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L);
+       }
+
+       void SetModify(BOOL bModified = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L);
+       }
+
+       void GetRect(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect);
+       }
+
+       DWORD GetSel() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L);
+       }
+
+       void GetSel(int& nStartChar, int& nEndChar) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
+       }
+
+#ifndef _WIN32_WCE
+       HLOCAL GetHandle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HLOCAL)::SendMessage(m_hWnd, EM_GETHANDLE, 0, 0L);
+       }
+
+       void SetHandle(HLOCAL hBuffer)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETHANDLE, (WPARAM)hBuffer, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       DWORD GetMargins() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_GETMARGINS, 0, 0L);
+       }
+
+       void SetMargins(UINT nLeft, UINT nRight)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(nLeft, nRight));
+       }
+
+       UINT GetLimitText() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L);
+       }
+
+       void SetLimitText(UINT nMax)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETLIMITTEXT, nMax, 0L);
+       }
+
+       POINT PosFromChar(UINT nChar) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_POSFROMCHAR, nChar, 0);
+               POINT point = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) };
+               return point;
+       }
+
+       int CharFromPos(POINT pt, int* pLine = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
+               if(pLine != NULL)
+                       *pLine = (int)(short)HIWORD(dwRet);
+               return (int)(short)LOWORD(dwRet);
+       }
+
+       // NOTE: first word in lpszBuffer must contain the size of the buffer!
+       int GetLine(int nIndex, LPTSTR lpszBuffer) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
+       }
+
+       int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               *(LPWORD)lpszBuffer = (WORD)nMaxLength;
+               return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
+       }
+
+       TCHAR GetPasswordChar() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (TCHAR)::SendMessage(m_hWnd, EM_GETPASSWORDCHAR, 0, 0L);
+       }
+
+       void SetPasswordChar(TCHAR ch)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETPASSWORDCHAR, ch, 0L);
+       }
+
+#ifndef _WIN32_WCE
+       EDITWORDBREAKPROC GetWordBreakProc() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (EDITWORDBREAKPROC)::SendMessage(m_hWnd, EM_GETWORDBREAKPROC, 0, 0L);
+       }
+
+       void SetWordBreakProc(EDITWORDBREAKPROC ewbprc)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc);
+       }
+#endif // !_WIN32_WCE
+
+       int GetFirstVisibleLine() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L);
+       }
+
+#ifndef _WIN32_WCE
+       int GetThumb() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & ES_MULTILINE) != 0);
+               return (int)::SendMessage(m_hWnd, EM_GETTHUMB, 0, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL SetReadOnly(BOOL bReadOnly = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L);
+       }
+
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+       UINT GetImeStatus(UINT uStatus) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_GETIMESTATUS, uStatus, 0L);
+       }
+
+       UINT SetImeStatus(UINT uStatus, UINT uData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_SETIMESTATUS, uStatus, uData);
+       }
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+
+#if (_WIN32_WINNT >= 0x0501)
+       BOOL GetCueBannerText(LPCWSTR lpstrText, int cchText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_GETCUEBANNER, (WPARAM)lpstrText, cchText);
+       }
+
+       // bKeepWithFocus - Vista only
+       BOOL SetCueBannerText(LPCWSTR lpstrText, BOOL bKeepWithFocus = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCUEBANNER, (WPARAM)bKeepWithFocus, (LPARAM)(lpstrText));
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+// Operations
+       void EmptyUndoBuffer()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L);
+       }
+
+       BOOL FmtLines(BOOL bAddEOL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_FMTLINES, bAddEOL, 0L);
+       }
+
+       void LimitText(int nChars = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_LIMITTEXT, nChars, 0L);
+       }
+
+       int LineFromChar(int nIndex = -1) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_LINEFROMCHAR, nIndex, 0L);
+       }
+
+       int LineIndex(int nLine = -1) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L);
+       }
+
+       int LineLength(int nLine = -1) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L);
+       }
+
+       void LineScroll(int nLines, int nChars = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_LINESCROLL, nChars, nLines);
+       }
+
+       void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
+       }
+
+       void SetRect(LPCRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect);
+       }
+
+       void SetRectNP(LPCRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETRECTNP, 0, (LPARAM)lpRect);
+       }
+
+       void SetSel(DWORD dwSelection, BOOL bNoScroll = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection));
+               if(!bNoScroll)
+                       ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
+       }
+
+       void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETSEL, nStartChar, nEndChar);
+               if(!bNoScroll)
+                       ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
+       }
+
+       void SetSelAll(BOOL bNoScroll = FALSE)
+       {
+               SetSel(0, -1, bNoScroll);
+       }
+
+       void SetSelNone(BOOL bNoScroll = FALSE)
+       {
+               SetSel(-1, 0, bNoScroll);
+       }
+
+       BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
+       }
+
+       BOOL SetTabStops()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L);
+       }
+
+       BOOL SetTabStops(const int& cxEachStop)    // takes an 'int'
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
+       }
+
+       void ScrollCaret()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
+       }
+
+       int Scroll(int nScrollAction)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & ES_MULTILINE) != 0);
+               LRESULT lRet = ::SendMessage(m_hWnd, EM_SCROLL, nScrollAction, 0L);
+               if(!(BOOL)HIWORD(lRet))
+                       return -1;   // failed
+               return (int)(short)LOWORD(lRet);
+               
+       }
+
+       void InsertText(int nInsertAfterChar, LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
+       {
+               SetSel(nInsertAfterChar, nInsertAfterChar, bNoScroll);
+               ReplaceSel(lpstrText, bCanUndo);
+       }
+
+       void AppendText(LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
+       {
+               InsertText(GetWindowTextLength(), lpstrText, bNoScroll, bCanUndo);
+       }
+
+#if (_WIN32_WINNT >= 0x0501)
+       BOOL ShowBalloonTip(PEDITBALLOONTIP pEditBaloonTip)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SHOWBALLOONTIP, 0, (LPARAM)pEditBaloonTip);
+       }
+
+       BOOL HideBalloonTip()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_HIDEBALLOONTIP, 0, 0L);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+#if (_WIN32_WINNT >= 0x0600)
+       DWORD GetHilite() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L);
+       }
+
+       void GetHilite(int& nStartChar, int& nEndChar) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L);
+               nStartChar = (int)(short)LOWORD(dwRet);
+               nEndChar = (int)(short)HIWORD(dwRet);
+       }
+
+       void SetHilite(int nStartChar, int nEndChar)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETHILITE, nStartChar, nEndChar);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+       // Clipboard operations
+       BOOL Undo()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L);
+       }
+
+       void Clear()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
+       }
+
+       void Copy()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_COPY, 0, 0L);
+       }
+
+       void Cut()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_CUT, 0, 0L);
+       }
+
+       void Paste()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
+       }
+
+#ifdef WIN32_PLATFORM_WFSP   // SmartPhone only messages
+       DWORD GetExtendedStyle()
+       {
+               return SendMessage(EM_GETEXTENDEDSTYLE);
+       }
+
+       DWORD SetExtendedStyle(DWORD dwMask, DWORD dwExStyle)
+       {
+               return SendMessage(EM_SETEXTENDEDSTYLE, (WPARAM)dwMask, (LPARAM)dwExStyle);
+       }
+
+       DWORD GetInputMode(BOOL bCurrentMode = TRUE)
+       {
+               return SendMessage(EM_GETINPUTMODE, 0, (LPARAM)bCurrentMode);
+       }
+
+       BOOL SetInputMode(DWORD dwMode)
+       {
+               return SendMessage(EM_SETINPUTMODE, 0, (LPARAM)dwMode);
+       }
+
+       BOOL SetSymbols(LPCTSTR szSymbols)
+       {
+               return SendMessage(EM_SETSYMBOLS, 0, (LPARAM)szSymbols);
+       }
+
+       BOOL ResetSymbols()
+       {
+               return SendMessage(EM_SETSYMBOLS);
+       }
+#endif // WIN32_PLATFORM_WFSP
+};
+
+typedef CEditT<ATL::CWindow>   CEdit;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CEditCommands - message handlers for standard EDIT commands
+
+// Chain to CEditCommands message map. Your class must also derive from CEdit.
+// Example:
+// class CMyEdit : public CWindowImpl<CMyEdit, CEdit>,
+//                 public CEditCommands<CMyEdit>
+// {
+// public:
+//      BEGIN_MSG_MAP(CMyEdit)
+//              // your handlers...
+//              CHAIN_MSG_MAP_ALT(CEditCommands<CMyEdit>, 1)
+//      END_MSG_MAP()
+//      // other stuff...
+// };
+
+template <class T>
+class CEditCommands
+{
+public:
+       BEGIN_MSG_MAP(CEditCommands< T >)
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_EDIT_CLEAR, OnEditClear)
+               COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, OnEditClearAll)
+               COMMAND_ID_HANDLER(ID_EDIT_COPY, OnEditCopy)
+               COMMAND_ID_HANDLER(ID_EDIT_CUT, OnEditCut)
+               COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnEditPaste)
+               COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnEditSelectAll)
+               COMMAND_ID_HANDLER(ID_EDIT_UNDO, OnEditUndo)
+       END_MSG_MAP()
+
+       LRESULT OnEditClear(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Clear();
+               return 0;
+       }
+
+       LRESULT OnEditClearAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetSel(0, -1);
+               pT->Clear();
+               return 0;
+       }
+
+       LRESULT OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Copy();
+               return 0;
+       }
+
+       LRESULT OnEditCut(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Cut();
+               return 0;
+       }
+
+       LRESULT OnEditPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Paste();
+               return 0;
+       }
+
+       LRESULT OnEditSelectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetSel(0, -1);
+               return 0;
+       }
+
+       LRESULT OnEditUndo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Undo();
+               return 0;
+       }
+
+// State (update UI) helpers
+       BOOL CanCut() const
+       { return HasSelection(); }
+
+       BOOL CanCopy() const
+       { return HasSelection(); }
+
+       BOOL CanClear() const
+       { return HasSelection(); }
+
+       BOOL CanSelectAll() const
+       { return HasText(); }
+
+       BOOL CanFind() const
+       { return HasText(); }
+
+       BOOL CanRepeat() const
+       { return HasText(); }
+
+       BOOL CanReplace() const
+       { return HasText(); }
+
+       BOOL CanClearAll() const
+       { return HasText(); }
+
+// Implementation
+       BOOL HasSelection() const
+       {
+               const T* pT = static_cast<const T*>(this);
+               int nMin, nMax;
+               ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nMin, (LPARAM)&nMax);
+               return (nMin != nMax);
+       }
+
+       BOOL HasText() const
+       {
+               const T* pT = static_cast<const T*>(this);
+               return (pT->GetWindowTextLength() > 0);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CScrollBar - client side for a Windows SCROLLBAR control
+
+template <class TBase>
+class CScrollBarT : public TBase
+{
+public:
+// Constructors
+       CScrollBarT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CScrollBarT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return _T("SCROLLBAR");
+       }
+
+#ifndef _WIN32_WCE
+       int GetScrollPos() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::GetScrollPos(m_hWnd, SB_CTL);
+       }
+#endif // !_WIN32_WCE
+
+       int SetScrollPos(int nPos, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SetScrollPos(m_hWnd, SB_CTL, nPos, bRedraw);
+       }
+
+#ifndef _WIN32_WCE
+       void GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::GetScrollRange(m_hWnd, SB_CTL, lpMinPos, lpMaxPos);
+       }
+#endif // !_WIN32_WCE
+
+       void SetScrollRange(int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SetScrollRange(m_hWnd, SB_CTL, nMinPos, nMaxPos, bRedraw);
+       }
+
+       BOOL GetScrollInfo(LPSCROLLINFO lpScrollInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::GetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo);
+       }
+
+       int SetScrollInfo(LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo, bRedraw);
+       }
+
+#ifndef _WIN32_WCE
+       int GetScrollLimit() const
+       {
+               int nMin = 0, nMax = 0;
+               ::GetScrollRange(m_hWnd, SB_CTL, &nMin, &nMax);
+               SCROLLINFO info = { 0 };
+               info.cbSize = sizeof(SCROLLINFO);
+               info.fMask = SIF_PAGE;
+               if(::GetScrollInfo(m_hWnd, SB_CTL, &info))
+                       nMax -= ((info.nPage - 1) > 0) ? (info.nPage - 1) : 0;
+
+               return nMax;
+       }
+
+#if (WINVER >= 0x0500)
+       BOOL GetScrollBarInfo(PSCROLLBARINFO pScrollBarInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+#if (_WIN32_WINNT >= 0x0501)
+               return (BOOL)::SendMessage(m_hWnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)pScrollBarInfo);
+#else // !(_WIN32_WINNT >= 0x0501)
+               return ::GetScrollBarInfo(m_hWnd, OBJID_CLIENT, pScrollBarInfo);
+#endif // !(_WIN32_WINNT >= 0x0501)
+       }
+#endif // (WINVER >= 0x0500)
+
+// Operations
+       void ShowScrollBar(BOOL bShow = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::ShowScrollBar(m_hWnd, SB_CTL, bShow);
+       }
+
+       BOOL EnableScrollBar(UINT nArrowFlags = ESB_ENABLE_BOTH)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::EnableScrollBar(m_hWnd, SB_CTL, nArrowFlags);
+       }
+#endif // !_WIN32_WCE
+};
+
+typedef CScrollBarT<ATL::CWindow>   CScrollBar;
+
+
+// --- Windows Common Controls ---
+
+///////////////////////////////////////////////////////////////////////////////
+// CImageList
+
+class CImageList
+{
+public:
+       HIMAGELIST m_hImageList;
+
+// Constructor
+       CImageList(HIMAGELIST hImageList = NULL) : m_hImageList(hImageList)
+       { }
+
+// Operators, etc.
+       CImageList& operator =(HIMAGELIST hImageList)
+       {
+               m_hImageList = hImageList;
+               return *this;
+       }
+
+       operator HIMAGELIST() const { return m_hImageList; }
+
+       void Attach(HIMAGELIST hImageList)
+       {
+               ATLASSERT(m_hImageList == NULL);
+               ATLASSERT(hImageList != NULL);
+               m_hImageList = hImageList;
+       }
+
+       HIMAGELIST Detach()
+       {
+               HIMAGELIST hImageList = m_hImageList;
+               m_hImageList = NULL;
+               return hImageList;
+       }
+
+       bool IsNull() const { return (m_hImageList == NULL); }
+
+// Attributes
+       int GetImageCount() const
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_GetImageCount(m_hImageList);
+       }
+
+       COLORREF GetBkColor() const
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_GetBkColor(m_hImageList);
+       }
+
+       COLORREF SetBkColor(COLORREF cr)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_SetBkColor(m_hImageList, cr);
+       }
+
+       BOOL GetImageInfo(int nImage, IMAGEINFO* pImageInfo) const
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_GetImageInfo(m_hImageList, nImage, pImageInfo);
+       }
+
+       HICON GetIcon(int nIndex, UINT uFlags = ILD_NORMAL) const
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_GetIcon(m_hImageList, nIndex, uFlags);
+       }
+
+       BOOL GetIconSize(int& cx, int& cy) const
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_GetIconSize(m_hImageList, &cx, &cy);
+       }
+
+       BOOL GetIconSize(SIZE& size) const
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_GetIconSize(m_hImageList, (int*)&size.cx, (int*)&size.cy);
+       }
+
+       BOOL SetIconSize(int cx, int cy)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_SetIconSize(m_hImageList, cx, cy);
+       }
+
+       BOOL SetIconSize(SIZE size)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_SetIconSize(m_hImageList, size.cx, size.cy);
+       }
+
+       BOOL SetImageCount(UINT uNewCount)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_SetImageCount(m_hImageList, uNewCount);
+       }
+
+       BOOL SetOverlayImage(int nImage, int nOverlay)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_SetOverlayImage(m_hImageList, nImage, nOverlay);
+       }
+
+// Operations
+       BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow)
+       {
+               ATLASSERT(m_hImageList == NULL);
+               m_hImageList = ImageList_Create(cx, cy, nFlags, nInitial, nGrow);
+               return (m_hImageList != NULL) ? TRUE : FALSE;
+       }
+
+       BOOL Create(ATL::_U_STRINGorID bitmap, int cx, int nGrow, COLORREF crMask)
+       {
+               ATLASSERT(m_hImageList == NULL);
+               m_hImageList = ImageList_LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, cx, nGrow, crMask);
+               return (m_hImageList != NULL) ? TRUE : FALSE;
+       }
+
+       BOOL CreateFromImage(ATL::_U_STRINGorID image, int cx, int nGrow, COLORREF crMask, UINT uType, UINT uFlags = LR_DEFAULTCOLOR | LR_DEFAULTSIZE)
+       {
+               ATLASSERT(m_hImageList == NULL);
+               m_hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, cx, nGrow, crMask, uType, uFlags);
+               return (m_hImageList != NULL) ? TRUE : FALSE;
+       }
+
+       BOOL Merge(HIMAGELIST hImageList1, int nImage1, HIMAGELIST hImageList2, int nImage2, int dx, int dy)
+       {
+               ATLASSERT(m_hImageList == NULL);
+               m_hImageList = ImageList_Merge(hImageList1, nImage1, hImageList2, nImage2, dx, dy);
+               return (m_hImageList != NULL) ? TRUE : FALSE;
+       }
+
+#ifndef _WIN32_WCE
+#ifdef __IStream_INTERFACE_DEFINED__
+       BOOL CreateFromStream(LPSTREAM lpStream)
+       {
+               ATLASSERT(m_hImageList == NULL);
+               m_hImageList = ImageList_Read(lpStream);
+               return (m_hImageList != NULL) ? TRUE : FALSE;
+       }
+#endif // __IStream_INTERFACE_DEFINED__
+#endif // !_WIN32_WCE
+
+       BOOL Destroy()
+       {
+               if (m_hImageList == NULL)
+                       return FALSE;
+               BOOL bRet = ImageList_Destroy(m_hImageList);
+               if(bRet)
+                       m_hImageList = NULL;
+               return bRet;
+       }
+
+       int Add(HBITMAP hBitmap, HBITMAP hBitmapMask = NULL)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_Add(m_hImageList, hBitmap, hBitmapMask);
+       }
+
+       int Add(HBITMAP hBitmap, COLORREF crMask)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_AddMasked(m_hImageList, hBitmap, crMask);
+       }
+
+       BOOL Remove(int nImage)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_Remove(m_hImageList, nImage);
+       }
+
+       BOOL RemoveAll()
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_RemoveAll(m_hImageList);
+       }
+
+       BOOL Replace(int nImage, HBITMAP hBitmap, HBITMAP hBitmapMask)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_Replace(m_hImageList, nImage, hBitmap, hBitmapMask);
+       }
+
+       int AddIcon(HICON hIcon)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_AddIcon(m_hImageList, hIcon);
+       }
+
+       int ReplaceIcon(int nImage, HICON hIcon)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_ReplaceIcon(m_hImageList, nImage, hIcon);
+       }
+
+       HICON ExtractIcon(int nImage)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_ExtractIcon(NULL, m_hImageList, nImage);
+       }
+
+       BOOL Draw(HDC hDC, int nImage, int x, int y, UINT nStyle)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               ATLASSERT(hDC != NULL);
+               return ImageList_Draw(m_hImageList, nImage, hDC, x, y, nStyle);
+       }
+
+       BOOL Draw(HDC hDC, int nImage, POINT pt, UINT nStyle)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               ATLASSERT(hDC != NULL);
+               return ImageList_Draw(m_hImageList, nImage, hDC, pt.x, pt.y, nStyle);
+       }
+
+       BOOL DrawEx(int nImage, HDC hDC, int x, int y, int dx, int dy, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               ATLASSERT(hDC != NULL);
+               return ImageList_DrawEx(m_hImageList, nImage, hDC, x, y, dx, dy, rgbBk, rgbFg, fStyle);
+       }
+
+       BOOL DrawEx(int nImage, HDC hDC, RECT& rect, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               ATLASSERT(hDC != NULL);
+               return ImageList_DrawEx(m_hImageList, nImage, hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, rgbBk, rgbFg, fStyle);
+       }
+
+       static BOOL DrawIndirect(IMAGELISTDRAWPARAMS* pimldp)
+       {
+               return ImageList_DrawIndirect(pimldp);
+       }
+
+       BOOL Copy(int nSrc, int nDst, UINT uFlags = ILCF_MOVE)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_Copy(m_hImageList, nDst, m_hImageList, nSrc, uFlags);
+       }
+
+#ifdef __IStream_INTERFACE_DEFINED__
+#ifndef _WIN32_WCE
+       static HIMAGELIST Read(LPSTREAM lpStream)
+       {
+               return ImageList_Read(lpStream);
+       }
+
+       BOOL Write(LPSTREAM lpStream)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_Write(m_hImageList, lpStream);
+       }
+#endif // !_WIN32_WCE
+
+#if (_WIN32_WINNT >= 0x0501)
+       static HRESULT ReadEx(DWORD dwFlags, LPSTREAM lpStream, REFIID riid, PVOID* ppv)
+       {
+               return ImageList_ReadEx(dwFlags, lpStream, riid, ppv);
+       }
+
+       HRESULT WriteEx(DWORD dwFlags, LPSTREAM lpStream)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_WriteEx(m_hImageList, dwFlags, lpStream);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+#endif // __IStream_INTERFACE_DEFINED__
+
+       // Drag operations
+       BOOL BeginDrag(int nImage, POINT ptHotSpot)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_BeginDrag(m_hImageList, nImage, ptHotSpot.x, ptHotSpot.y);
+       }
+
+       BOOL BeginDrag(int nImage, int xHotSpot, int yHotSpot)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_BeginDrag(m_hImageList, nImage, xHotSpot, yHotSpot);
+       }
+
+       static void EndDrag()
+       {
+               ImageList_EndDrag();
+       }
+
+       static BOOL DragMove(POINT pt)
+       {
+               return ImageList_DragMove(pt.x, pt.y);
+       }
+
+       static BOOL DragMove(int x, int y)
+       {
+               return ImageList_DragMove(x, y);
+       }
+
+       BOOL SetDragCursorImage(int nDrag, POINT ptHotSpot)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_SetDragCursorImage(m_hImageList, nDrag, ptHotSpot.x, ptHotSpot.y);
+       }
+
+       BOOL SetDragCursorImage(int nDrag, int xHotSpot, int yHotSpot)
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return ImageList_SetDragCursorImage(m_hImageList, nDrag, xHotSpot, yHotSpot);
+       }
+
+       static BOOL DragShowNolock(BOOL bShow = TRUE)
+       {
+               return ImageList_DragShowNolock(bShow);
+       }
+
+       static CImageList GetDragImage(LPPOINT lpPoint, LPPOINT lpPointHotSpot)
+       {
+               return CImageList(ImageList_GetDragImage(lpPoint, lpPointHotSpot));
+       }
+
+       static BOOL DragEnter(HWND hWnd, POINT point)
+       {
+               return ImageList_DragEnter(hWnd, point.x, point.y);
+       }
+
+       static BOOL DragEnter(HWND hWnd, int x, int y)
+       {
+               return ImageList_DragEnter(hWnd, x, y);
+       }
+
+       static BOOL DragLeave(HWND hWnd)
+       {
+               return ImageList_DragLeave(hWnd);
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       CImageList Duplicate() const
+       {
+               ATLASSERT(m_hImageList != NULL);
+               return CImageList(ImageList_Duplicate(m_hImageList));
+       }
+
+       static CImageList Duplicate(HIMAGELIST hImageList)
+       {
+               ATLASSERT(hImageList != NULL);
+               return CImageList(ImageList_Duplicate(hImageList));
+       }
+#endif // (_WIN32_IE >= 0x0400)
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CToolTipCtrl
+
+#ifndef _WIN32_WCE
+
+class CToolInfo : public TOOLINFO
+{
+public:
+       CToolInfo(UINT nFlags, HWND hWnd, UINT nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL)
+       {
+               Init(nFlags, hWnd, nIDTool, lpRect, lpstrText, lUserParam);
+       }
+
+       operator LPTOOLINFO() { return this; }
+
+       operator LPARAM() { return (LPARAM)this; }
+
+       void Init(UINT nFlags, HWND hWnd, UINT nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL)
+       {
+               ATLASSERT(::IsWindow(hWnd));
+               memset(this, 0, sizeof(TOOLINFO));
+               cbSize = sizeof(TOOLINFO);
+               uFlags = nFlags;
+               if(nIDTool == 0)
+               {
+                       hwnd = ::GetParent(hWnd);
+                       uFlags |= TTF_IDISHWND;
+                       uId = (UINT_PTR)hWnd;
+               }
+               else
+               {
+                       hwnd = hWnd;
+                       uId = nIDTool;
+               }
+               if(lpRect != NULL)
+                       rect = *lpRect;
+               hinst = ModuleHelper::GetResourceInstance();
+               lpszText = lpstrText;
+               lParam = lUserParam;
+       }
+};
+
+template <class TBase>
+class CToolTipCtrlT : public TBase
+{
+public:
+// Constructors
+       CToolTipCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CToolTipCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return TOOLTIPS_CLASS;
+       }
+
+       void GetText(LPTOOLINFO lpToolInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_GETTEXT, 0, (LPARAM)&lpToolInfo);
+       }
+
+       void GetText(LPTSTR lpstrText, HWND hWnd, UINT nIDTool = 0) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hWnd != NULL);
+               CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText);
+               ::SendMessage(m_hWnd, TTM_GETTEXT, 0, ti);
+       }
+
+       BOOL GetToolInfo(LPTOOLINFO lpToolInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, (LPARAM)lpToolInfo);
+       }
+
+       BOOL GetToolInfo(HWND hWnd, UINT nIDTool, UINT* puFlags, LPRECT lpRect, LPTSTR lpstrText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hWnd != NULL);
+               ATLASSERT(puFlags != NULL);
+               ATLASSERT(lpRect != NULL);
+               CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText);
+               BOOL bRet = (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, ti);
+               if(bRet != FALSE)
+               {
+                       *puFlags = ti.uFlags;
+                       *lpRect = ti.rect;
+               }
+               return bRet;
+       }
+
+       void SetToolInfo(LPTOOLINFO lpToolInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_SETTOOLINFO, 0, (LPARAM)lpToolInfo);
+       }
+
+       void SetToolRect(LPTOOLINFO lpToolInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, (LPARAM)lpToolInfo);
+       }
+
+       void SetToolRect(HWND hWnd, UINT nIDTool, LPCRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hWnd != NULL);
+               ATLASSERT(nIDTool != 0);
+
+               CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRect, NULL);
+               ::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, ti);
+       }
+
+       int GetToolCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TTM_GETTOOLCOUNT, 0, 0L);
+       }
+
+       int GetDelayTime(DWORD dwType) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TTM_GETDELAYTIME, dwType, 0L);
+       }
+
+       void SetDelayTime(DWORD dwType, int nTime)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_SETDELAYTIME, dwType, MAKELPARAM(nTime, 0));
+       }
+
+       void GetMargin(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_GETMARGIN, 0, (LPARAM)lpRect);
+       }
+
+       void SetMargin(LPRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_SETMARGIN, 0, (LPARAM)lpRect);
+       }
+
+       int GetMaxTipWidth() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TTM_GETMAXTIPWIDTH, 0, 0L);
+       }
+
+       int SetMaxTipWidth(int nWidth)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TTM_SETMAXTIPWIDTH, 0, nWidth);
+       }
+
+       COLORREF GetTipBkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPBKCOLOR, 0, 0L);
+       }
+
+       void SetTipBkColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_SETTIPBKCOLOR, (WPARAM)clr, 0L);
+       }
+
+       COLORREF GetTipTextColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPTEXTCOLOR, 0, 0L);
+       }
+
+       void SetTipTextColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_SETTIPTEXTCOLOR, (WPARAM)clr, 0L);
+       }
+
+       BOOL GetCurrentTool(LPTOOLINFO lpToolInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TTM_GETCURRENTTOOL, 0, (LPARAM)lpToolInfo);
+       }
+
+#if (_WIN32_IE >= 0x0500)
+       SIZE GetBubbleSize(LPTOOLINFO lpToolInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TTM_GETBUBBLESIZE, 0, (LPARAM)lpToolInfo);
+               SIZE size = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) };
+               return size;
+       }
+
+       BOOL SetTitle(UINT uIcon, LPCTSTR lpstrTitle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TTM_SETTITLE, uIcon, (LPARAM)lpstrTitle);
+       }
+#endif // (_WIN32_IE >= 0x0500)
+
+#if (_WIN32_WINNT >= 0x0501)
+       void GetTitle(PTTGETTITLE pTTGetTitle) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_GETTITLE, 0, (LPARAM)pTTGetTitle);
+       }
+
+       void SetWindowTheme(LPCWSTR lpstrTheme)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+// Operations
+       void Activate(BOOL bActivate)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_ACTIVATE, bActivate, 0L);
+       }
+
+       BOOL AddTool(LPTOOLINFO lpToolInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, (LPARAM)lpToolInfo);
+       }
+
+       BOOL AddTool(HWND hWnd, ATL::_U_STRINGorID text = LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT nIDTool = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hWnd != NULL);
+               // the toolrect and toolid must both be zero or both valid
+               ATLASSERT((lpRectTool != NULL && nIDTool != 0) || (lpRectTool == NULL && nIDTool == 0));
+
+               CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRectTool, (LPTSTR)text.m_lpstr);
+               return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, ti);
+       }
+
+       void DelTool(LPTOOLINFO lpToolInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_DELTOOL, 0, (LPARAM)lpToolInfo);
+       }
+
+       void DelTool(HWND hWnd, UINT nIDTool = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hWnd != NULL);
+
+               CToolInfo ti(0, hWnd, nIDTool, NULL, NULL);
+               ::SendMessage(m_hWnd, TTM_DELTOOL, 0, ti);
+       }
+
+       BOOL HitTest(LPTTHITTESTINFO lpHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)lpHitTestInfo);
+       }
+
+       BOOL HitTest(HWND hWnd, POINT pt, LPTOOLINFO lpToolInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hWnd != NULL);
+               ATLASSERT(lpToolInfo != NULL);
+
+               TTHITTESTINFO hti = { 0 };
+               hti.ti.cbSize = sizeof(TOOLINFO);
+               hti.hwnd = hWnd;
+               hti.pt.x = pt.x;
+               hti.pt.y = pt.y;
+               if((BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)&hti) != FALSE)
+               {
+                       *lpToolInfo = hti.ti;
+                       return TRUE;
+               }
+               return FALSE;
+       }
+
+       void RelayEvent(LPMSG lpMsg)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_RELAYEVENT, 0, (LPARAM)lpMsg);
+       }
+
+       void UpdateTipText(LPTOOLINFO lpToolInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, (LPARAM)lpToolInfo);
+       }
+
+       void UpdateTipText(ATL::_U_STRINGorID text, HWND hWnd, UINT nIDTool = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hWnd != NULL);
+
+               CToolInfo ti(0, hWnd, nIDTool, NULL, (LPTSTR)text.m_lpstr);
+               ::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, ti);
+       }
+
+       BOOL EnumTools(UINT nTool, LPTOOLINFO lpToolInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TTM_ENUMTOOLS, nTool, (LPARAM)lpToolInfo);
+       }
+
+       void Pop()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_POP, 0, 0L);
+       }
+
+       void TrackActivate(LPTOOLINFO lpToolInfo, BOOL bActivate)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_TRACKACTIVATE, bActivate, (LPARAM)lpToolInfo);
+       }
+
+       void TrackPosition(int xPos, int yPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_TRACKPOSITION, 0, MAKELPARAM(xPos, yPos));
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       void Update()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_UPDATE, 0, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500)
+       BOOL AdjustRect(LPRECT lpRect, BOOL bLarger /*= TRUE*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TTM_ADJUSTRECT, bLarger, (LPARAM)lpRect);
+       }
+#endif // (_WIN32_IE >= 0x0500)
+
+#if (_WIN32_WINNT >= 0x0501)
+       void Popup()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TTM_POPUP, 0, 0L);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+};
+
+typedef CToolTipCtrlT<ATL::CWindow>   CToolTipCtrl;
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CHeaderCtrl
+
+template <class TBase>
+class CHeaderCtrlT : public TBase
+{
+public:
+// Constructors
+       CHeaderCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CHeaderCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_HEADER;
+       }
+
+       int GetItemCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_GETITEMCOUNT, 0, 0L);
+       }
+
+       BOOL GetItem(int nIndex, LPHDITEM pHeaderItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_GETITEM, nIndex, (LPARAM)pHeaderItem);
+       }
+
+       BOOL SetItem(int nIndex, LPHDITEM pHeaderItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_SETITEM, nIndex, (LPARAM)pHeaderItem);
+       }
+
+       CImageList GetImageList() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_GETIMAGELIST, 0, 0L));
+       }
+
+       CImageList SetImageList(HIMAGELIST hImageList)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_SETIMAGELIST, 0, (LPARAM)hImageList));
+       }
+
+       BOOL GetOrderArray(int nSize, int* lpnArray) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_GETORDERARRAY, nSize, (LPARAM)lpnArray);
+       }
+
+       BOOL SetOrderArray(int nSize, int* lpnArray)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_SETORDERARRAY, nSize, (LPARAM)lpnArray);
+       }
+
+       BOOL GetItemRect(int nIndex, LPRECT lpItemRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMRECT, nIndex, (LPARAM)lpItemRect);
+       }
+
+       int SetHotDivider(BOOL bPos, DWORD dwInputValue)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_SETHOTDIVIDER, bPos, dwInputValue);
+       }
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       int GetBitmapMargin() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_GETBITMAPMARGIN, 0, 0L);
+       }
+
+       int SetBitmapMargin(int nWidth)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_SETBITMAPMARGIN, nWidth, 0L);
+       }
+
+       int SetFilterChangeTimeout(DWORD dwTimeOut)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_SETFILTERCHANGETIMEOUT, 0, dwTimeOut);
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+#if (_WIN32_WINNT >= 0x0600)
+       BOOL GetItemDropDownRect(int nIndex, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMDROPDOWNRECT, nIndex, (LPARAM)lpRect);
+       }
+
+       BOOL GetOverflowRect(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_GETOVERFLOWRECT, 0, (LPARAM)lpRect);
+       }
+
+       int GetFocusedItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_GETFOCUSEDITEM, 0, 0L);
+       }
+
+       BOOL SetFocusedItem(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_SETFOCUSEDITEM, 0, nIndex);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+// Operations
+       int InsertItem(int nIndex, LPHDITEM phdi)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_INSERTITEM, nIndex, (LPARAM)phdi);
+       }
+
+       int AddItem(LPHDITEM phdi)
+       {
+               return InsertItem(GetItemCount(), phdi);
+       }
+
+       BOOL DeleteItem(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_DELETEITEM, nIndex, 0L);
+       }
+
+       BOOL Layout(HD_LAYOUT* pHeaderLayout)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, HDM_LAYOUT, 0, (LPARAM)pHeaderLayout);
+       }
+
+       int HitTest(LPHDHITTESTINFO lpHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_HITTEST, 0, (LPARAM)lpHitTestInfo);
+       }
+
+       int OrderToIndex(int nOrder)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_ORDERTOINDEX, nOrder, 0L);
+       }
+
+       CImageList CreateDragImage(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_CREATEDRAGIMAGE, nIndex, 0L));
+       }
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       int EditFilter(int nColumn, BOOL bDiscardChanges)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_EDITFILTER, nColumn, MAKELPARAM(bDiscardChanges, 0));
+       }
+
+       int ClearFilter(int nColumn)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, nColumn, 0L);
+       }
+
+       int ClearAllFilters()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, (WPARAM)-1, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+};
+
+typedef CHeaderCtrlT<ATL::CWindow>   CHeaderCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CListViewCtrl
+
+template <class TBase>
+class CListViewCtrlT : public TBase
+{
+public:
+// Constructors
+       CListViewCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CListViewCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_LISTVIEW;
+       }
+
+       COLORREF GetBkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, LVM_GETBKCOLOR, 0, 0L);
+       }
+
+       BOOL SetBkColor(COLORREF cr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETBKCOLOR, 0, cr);
+       }
+
+       CImageList GetImageList(int nImageListType) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_GETIMAGELIST, nImageListType, 0L));
+       }
+
+       CImageList SetImageList(HIMAGELIST hImageList, int nImageList)
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, nImageList, (LPARAM)hImageList));
+       }
+
+       int GetItemCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETITEMCOUNT, 0, 0L);
+       }
+
+       BOOL SetItemCount(int nItems)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, 0L);
+       }
+
+       BOOL GetItem(LPLVITEM pItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem);
+       }
+
+       BOOL SetItem(const LVITEM* pItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)pItem);
+       }
+
+       BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem,
+               int nImage, UINT nState, UINT nStateMask, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVITEM lvi = { 0 };
+               lvi.mask = nMask;
+               lvi.iItem = nItem;
+               lvi.iSubItem = nSubItem;
+               lvi.stateMask = nStateMask;
+               lvi.state = nState;
+               lvi.pszText = (LPTSTR) lpszItem;
+               lvi.iImage = nImage;
+               lvi.lParam = lParam;
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)&lvi);
+       }
+
+       UINT GetItemState(int nItem, UINT nMask) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, LVM_GETITEMSTATE, nItem, nMask);
+       }
+
+       BOOL SetItemState(int nItem, UINT nState, UINT nStateMask)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVITEM lvi = { 0 };
+               lvi.state = nState;
+               lvi.stateMask = nStateMask;
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)&lvi);
+       }
+
+       BOOL SetItemState(int nItem, LPLVITEM pItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)pItem);
+       }
+
+#ifndef _ATL_NO_COM
+       BOOL GetItemText(int nItem, int nSubItem, BSTR& bstrText) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(bstrText == NULL);
+               LVITEM lvi = { 0 };
+               lvi.iSubItem = nSubItem;
+
+               LPTSTR lpstrText = NULL;
+               int nRes = 0;
+               for(int nLen = 256; ; nLen *= 2)
+               {
+                       ATLTRY(lpstrText = new TCHAR[nLen]);
+                       if(lpstrText == NULL)
+                               break;
+                       lpstrText[0] = NULL;
+                       lvi.cchTextMax = nLen;
+                       lvi.pszText = lpstrText;
+                       nRes  = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
+                       if(nRes < nLen - 1)
+                               break;
+                       delete [] lpstrText;
+                       lpstrText = NULL;
+               }
+
+               if(lpstrText != NULL)
+               {
+                       if(nRes != 0)
+                               bstrText = ::SysAllocString(T2OLE(lpstrText));
+                       delete [] lpstrText;
+               }
+
+               return (bstrText != NULL) ? TRUE : FALSE;
+       }
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       int GetItemText(int nItem, int nSubItem, _CSTRING_NS::CString& strText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVITEM lvi = { 0 };
+               lvi.iSubItem = nSubItem;
+
+               strText.Empty();
+               int nRes = 0;
+               for(int nLen = 256; ; nLen *= 2)
+               {
+                       lvi.cchTextMax = nLen;
+                       lvi.pszText = strText.GetBufferSetLength(nLen);
+                       if(lvi.pszText == NULL)
+                       {
+                               nRes = 0;
+                               break;
+                       }
+                       nRes  = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
+                       if(nRes < nLen - 1)
+                               break;
+               }
+               strText.ReleaseBuffer();
+               return nRes;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       int GetItemText(int nItem, int nSubItem, LPTSTR lpszText, int nLen) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVITEM lvi = { 0 };
+               lvi.iSubItem = nSubItem;
+               lvi.cchTextMax = nLen;
+               lvi.pszText = lpszText;
+               return (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
+       }
+
+       BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItem(nItem, nSubItem, LVIF_TEXT, lpszText, 0, 0, 0, 0);
+       }
+
+       DWORD_PTR GetItemData(int nItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVITEM lvi = { 0 };
+               lvi.iItem = nItem;
+               lvi.mask = LVIF_PARAM;
+               BOOL bRet = (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)&lvi);
+               return (DWORD_PTR)(bRet ? lvi.lParam : NULL);
+       }
+
+       BOOL SetItemData(int nItem, DWORD_PTR dwData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItem(nItem, 0, LVIF_PARAM, NULL, 0, 0, 0, (LPARAM)dwData);
+       }
+
+       UINT GetCallbackMask() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, LVM_GETCALLBACKMASK, 0, 0L);
+       }
+
+       BOOL SetCallbackMask(UINT nMask)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETCALLBACKMASK, nMask, 0L);
+       }
+
+       BOOL GetItemPosition(int nItem, LPPOINT lpPoint) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMPOSITION, nItem, (LPARAM)lpPoint);
+       }
+
+       BOOL SetItemPosition(int nItem, POINT pt)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
+       }
+
+       BOOL SetItemPosition(int nItem, int x, int y)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
+               POINT pt = { x, y };
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
+       }
+
+       int GetStringWidth(LPCTSTR lpsz) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETSTRINGWIDTH, 0, (LPARAM)lpsz);
+       }
+
+       CEdit GetEditControl() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CEdit((HWND)::SendMessage(m_hWnd, LVM_GETEDITCONTROL, 0, 0L));
+       }
+
+       BOOL GetColumn(int nCol, LVCOLUMN* pColumn) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMN, nCol, (LPARAM)pColumn);
+       }
+
+       BOOL SetColumn(int nCol, const LVCOLUMN* pColumn)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMN, nCol, (LPARAM)pColumn);
+       }
+
+       int GetColumnWidth(int nCol) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETCOLUMNWIDTH, nCol, 0L);
+       }
+
+       BOOL SetColumnWidth(int nCol, int cx)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNWIDTH, nCol, MAKELPARAM(cx, 0));
+       }
+
+       BOOL GetViewRect(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETVIEWRECT, 0, (LPARAM)lpRect);
+       }
+
+       COLORREF GetTextColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTCOLOR, 0, 0L);
+       }
+
+       BOOL SetTextColor(COLORREF cr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTCOLOR, 0, cr);
+       }
+
+       COLORREF GetTextBkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTBKCOLOR, 0, 0L);
+       }
+
+       BOOL SetTextBkColor(COLORREF cr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTBKCOLOR, 0, cr);
+       }
+
+       int GetTopIndex() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETTOPINDEX, 0, 0L);
+       }
+
+       int GetCountPerPage() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETCOUNTPERPAGE, 0, 0L);
+       }
+
+       BOOL GetOrigin(LPPOINT lpPoint) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETORIGIN, 0, (LPARAM)lpPoint);
+       }
+
+       UINT GetSelectedCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, LVM_GETSELECTEDCOUNT, 0, 0L);
+       }
+
+       BOOL GetItemRect(int nItem, LPRECT lpRect, UINT nCode) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               lpRect->left = nCode;
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMRECT, (WPARAM)nItem, (LPARAM)lpRect);
+       }
+
+#ifndef _WIN32_WCE
+       HCURSOR GetHotCursor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HCURSOR)::SendMessage(m_hWnd, LVM_GETHOTCURSOR, 0, 0L);
+       }
+
+       HCURSOR SetHotCursor(HCURSOR hHotCursor)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HCURSOR)::SendMessage(m_hWnd, LVM_SETHOTCURSOR, 0, (LPARAM)hHotCursor);
+       }
+
+       int GetHotItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETHOTITEM, 0, 0L);
+       }
+
+       int SetHotItem(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_SETHOTITEM, nIndex, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL GetColumnOrderArray(int nCount, int* lpnArray) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
+       }
+
+       BOOL SetColumnOrderArray(int nCount, int* lpnArray)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
+       }
+
+       CHeaderCtrl GetHeader() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CHeaderCtrl((HWND)::SendMessage(m_hWnd, LVM_GETHEADER, 0, 0L));
+       }
+
+       BOOL GetSubItemRect(int nItem, int nSubItem, int nFlag, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_REPORT);
+               ATLASSERT(lpRect != NULL);
+               lpRect->top = nSubItem;
+               lpRect->left = nFlag;
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETSUBITEMRECT, nItem, (LPARAM)lpRect);
+       }
+
+       DWORD SetIconSpacing(int cx, int cy)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_ICON);
+               return (DWORD)::SendMessage(m_hWnd, LVM_SETICONSPACING, 0, MAKELPARAM(cx, cy));
+       }
+
+       int GetISearchString(LPTSTR lpstr) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
+       }
+
+       void GetItemSpacing(SIZE& sizeSpacing, BOOL bSmallIconView = FALSE) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, LVM_GETITEMSPACING, bSmallIconView, 0L);
+               sizeSpacing.cx = GET_X_LPARAM(dwRet);
+               sizeSpacing.cy = GET_Y_LPARAM(dwRet);
+       }
+
+#if (_WIN32_WCE >= 410)
+       void SetItemSpacing(INT cySpacing)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ListView_SetItemSpacing(m_hWnd, cySpacing);
+       }
+#endif // (_WIN32_WCE >= 410)
+
+       // single-selection only
+       int GetSelectedIndex() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0);
+               return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
+       }
+
+       BOOL GetSelectedItem(LPLVITEM pItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0);
+               ATLASSERT(pItem != NULL);
+               pItem->iItem = (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
+               if(pItem->iItem == -1)
+                       return FALSE;
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem);
+       }
+
+       // extended list view styles
+       DWORD GetExtendedListViewStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L);
+       }
+
+       // dwExMask = 0 means all styles
+       DWORD SetExtendedListViewStyle(DWORD dwExStyle, DWORD dwExMask = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, dwExMask, dwExStyle);
+       }
+
+       // checkboxes only
+       BOOL GetCheckState(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetExtendedListViewStyle() & LVS_EX_CHECKBOXES) != 0);
+               UINT uRet = GetItemState(nIndex, LVIS_STATEIMAGEMASK);
+               return (uRet >> 12) - 1;
+       }
+
+       BOOL SetCheckState(int nItem, BOOL bCheck)
+       {
+               int nCheck = bCheck ? 2 : 1;   // one based index
+               return SetItemState(nItem, INDEXTOSTATEIMAGEMASK(nCheck), LVIS_STATEIMAGEMASK);
+       }
+
+       // view type
+       DWORD GetViewType() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (GetStyle() & LVS_TYPEMASK);
+       }
+
+       DWORD SetViewType(DWORD dwType)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(dwType == LVS_ICON || dwType == LVS_SMALLICON || dwType == LVS_LIST || dwType == LVS_REPORT);
+               DWORD dwOldType = GetViewType();
+               if(dwType != dwOldType)
+                       ModifyStyle(LVS_TYPEMASK, (dwType & LVS_TYPEMASK));
+               return dwOldType;
+       }
+
+#if (_WIN32_IE >= 0x0400)
+#ifndef _WIN32_WCE
+       BOOL GetBkImage(LPLVBKIMAGE plvbki) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETBKIMAGE, 0, (LPARAM)plvbki);
+       }
+
+       BOOL SetBkImage(LPLVBKIMAGE plvbki)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETBKIMAGE, 0, (LPARAM)plvbki);
+       }
+#endif // !_WIN32_WCE
+
+       int GetSelectionMark() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETSELECTIONMARK, 0, 0L);
+       }
+
+       int SetSelectionMark(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_SETSELECTIONMARK, 0, nIndex);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetWorkAreas(int nWorkAreas, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
+       }
+
+       BOOL SetWorkAreas(int nWorkAreas, LPRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
+       }
+
+       DWORD GetHoverTime() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
+               return (DWORD)::SendMessage(m_hWnd, LVM_GETHOVERTIME, 0, 0L);
+       }
+
+       DWORD SetHoverTime(DWORD dwHoverTime)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
+               return (DWORD)::SendMessage(m_hWnd, LVM_SETHOVERTIME, 0, dwHoverTime);
+       }
+
+       BOOL GetNumberOfWorkAreas(int* pnWorkAreas) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETNUMBEROFWORKAREAS, 0, (LPARAM)pnWorkAreas);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL SetItemCountEx(int nItems, DWORD dwFlags)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(((GetStyle() & LVS_OWNERDATA) != 0) && (((GetStyle() & LVS_TYPEMASK) == LVS_REPORT) || ((GetStyle() & LVS_TYPEMASK) == LVS_LIST)));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, dwFlags);
+       }
+
+#ifndef _WIN32_WCE
+       CToolTipCtrl GetToolTips() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_GETTOOLTIPS, 0, 0L));
+       }
+
+       CToolTipCtrl SetToolTips(HWND hWndTT)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
+       }
+
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // !_WIN32_WCE
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_WINNT >= 0x0501)
+       int GetSelectedColumn() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETSELECTEDCOLUMN, 0, 0L);
+       }
+
+       void SetSelectedColumn(int nColumn)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_SETSELECTEDCOLUMN, nColumn, 0L);
+       }
+
+       DWORD GetView() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, LVM_GETVIEW, 0, 0L);
+       }
+
+       int SetView(DWORD dwView)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_SETVIEW, dwView, 0L);
+       }
+
+       BOOL IsGroupViewEnabled() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_ISGROUPVIEWENABLED, 0, 0L);
+       }
+
+       int GetGroupInfo(int nGroupID, PLVGROUP pGroup) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETGROUPINFO, nGroupID, (LPARAM)pGroup);
+       }
+
+       int SetGroupInfo(int nGroupID, PLVGROUP pGroup)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_SETGROUPINFO, nGroupID, (LPARAM)pGroup);
+       }
+
+       void GetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_GETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
+       }
+
+       void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_SETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
+       }
+
+       void GetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_GETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
+       }
+
+       BOOL SetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
+       }
+
+       void GetTileInfo(PLVTILEINFO pTileInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_GETTILEINFO, 0, (LPARAM)pTileInfo);
+       }
+
+       BOOL SetTileInfo(PLVTILEINFO pTileInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEINFO, 0, (LPARAM)pTileInfo);
+       }
+
+       BOOL GetInsertMark(LPLVINSERTMARK pInsertMark) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETINSERTMARK, 0, (LPARAM)pInsertMark);
+       }
+
+       BOOL SetInsertMark(LPLVINSERTMARK pInsertMark)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETINSERTMARK, 0, (LPARAM)pInsertMark);
+       }
+
+       int GetInsertMarkRect(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETINSERTMARKRECT, 0, (LPARAM)lpRect);
+       }
+
+       COLORREF GetInsertMarkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, LVM_GETINSERTMARKCOLOR, 0, 0L);
+       }
+
+       COLORREF SetInsertMarkColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, LVM_SETINSERTMARKCOLOR, 0, clr);
+       }
+
+       COLORREF GetOutlineColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, LVM_GETOUTLINECOLOR, 0, 0L);
+       }
+
+       COLORREF SetOutlineColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, LVM_SETOUTLINECOLOR, 0, clr);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+#if (_WIN32_WINNT >= 0x0600)
+       int GetGroupCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETGROUPCOUNT, 0, 0L);
+       }
+
+       BOOL GetGroupInfoByIndex(int nIndex, PLVGROUP pGroup) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPINFOBYINDEX, nIndex, (LPARAM)pGroup);
+       }
+
+       BOOL GetGroupRect(int nGroupID, int nType, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpRect != NULL);
+               if(lpRect != NULL)
+                       lpRect->top = nType;
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPRECT, nGroupID, (LPARAM)lpRect);
+       }
+
+       UINT GetGroupState(int nGroupID, UINT uMask) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, LVM_GETGROUPSTATE, nGroupID, (LPARAM)uMask);
+       }
+
+       int GetFocusedGroup() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETFOCUSEDGROUP, 0, 0L);
+       }
+
+       BOOL GetEmptyText(LPWSTR lpstrText, int cchText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETEMPTYTEXT, cchText, (LPARAM)lpstrText);
+       }
+
+       BOOL GetFooterRect(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERRECT, 0, (LPARAM)lpRect);
+       }
+
+       BOOL GetFooterInfo(LPLVFOOTERINFO lpFooterInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERINFO, 0, (LPARAM)lpFooterInfo);
+       }
+
+       BOOL GetFooterItemRect(int nItem, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEMRECT, nItem, (LPARAM)lpRect);
+       }
+
+       BOOL GetFooterItem(int nItem, LPLVFOOTERITEM lpFooterItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEM, nItem, (LPARAM)lpFooterItem);
+       }
+
+       BOOL GetItemIndexRect(PLVITEMINDEX pItemIndex, int nSubItem, int nType, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pItemIndex != NULL);
+               ATLASSERT(lpRect != NULL);
+               if(lpRect != NULL)
+               {
+                       lpRect->top = nSubItem;
+                       lpRect->left = nType;
+               }
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMINDEXRECT, (WPARAM)pItemIndex, (LPARAM)lpRect);
+       }
+
+       BOOL SetItemIndexState(PLVITEMINDEX pItemIndex, UINT uState, UINT dwMask)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVITEM lvi = { 0 };
+               lvi.state = uState;
+               lvi.stateMask = dwMask;
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMINDEXSTATE, (WPARAM)pItemIndex, (LPARAM)&lvi);
+       }
+
+       BOOL GetNextItemIndex(PLVITEMINDEX pItemIndex, WORD wFlags) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_GETNEXTITEMINDEX, (WPARAM)pItemIndex, MAKELPARAM(wFlags, 0));
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+// Operations
+       int InsertColumn(int nCol, const LVCOLUMN* pColumn)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn);
+       }
+
+       int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, 
+                       int nWidth = -1, int nSubItem = -1, int iImage = -1, int iOrder = -1)
+       {
+               LVCOLUMN column = { 0 };
+               column.mask = LVCF_TEXT|LVCF_FMT;
+               column.pszText = (LPTSTR)lpszColumnHeading;
+               column.fmt = nFormat;
+               if (nWidth != -1)
+               {
+                       column.mask |= LVCF_WIDTH;
+                       column.cx = nWidth;
+               }
+               if (nSubItem != -1)
+               {
+                       column.mask |= LVCF_SUBITEM;
+                       column.iSubItem = nSubItem;
+               }
+               if (iImage != -1)
+               {
+                       column.mask |= LVCF_IMAGE;
+                       column.iImage = iImage;
+               }
+               if (iOrder != -1)
+               {
+                       column.mask |= LVCF_ORDER;
+                       column.iOrder = iOrder;
+               }
+               return InsertColumn(nCol, &column);
+       }
+
+       BOOL DeleteColumn(int nCol)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_DELETECOLUMN, nCol, 0L);
+       }
+
+       int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVITEM item = { 0 };
+               item.mask = nMask;
+               item.iItem = nItem;
+               item.iSubItem = 0;
+               item.pszText = (LPTSTR)lpszItem;
+               item.state = nState;
+               item.stateMask = nStateMask;
+               item.iImage = nImage;
+               item.lParam = lParam;
+               return InsertItem(&item);
+       }
+
+       int InsertItem(const LVITEM* pItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_INSERTITEM, 0, (LPARAM)pItem);
+       }
+
+       int InsertItem(int nItem, LPCTSTR lpszItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return InsertItem(LVIF_TEXT, nItem, lpszItem, 0, 0, 0, 0);
+       }
+
+       int InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0);
+       }
+
+       int GetNextItem(int nItem, int nFlags) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, nItem, MAKELPARAM(nFlags, 0));
+       }
+
+       BOOL DeleteItem(int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_DELETEITEM, nItem, 0L);
+       }
+
+       BOOL DeleteAllItems()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_DELETEALLITEMS, 0, 0L);
+       }
+
+       int FindItem(LVFINDINFO* pFindInfo, int nStart) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo);
+       }
+
+       int HitTest(LVHITTESTINFO* pHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)pHitTestInfo);
+       }
+
+       int HitTest(POINT pt, UINT* pFlags) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVHITTESTINFO hti = { 0 };
+               hti.pt = pt;
+               int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)&hti);
+               if (pFlags != NULL)
+                       *pFlags = hti.flags;
+               return nRes;
+       }
+
+       BOOL EnsureVisible(int nItem, BOOL bPartialOK)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_ENSUREVISIBLE, nItem, MAKELPARAM(bPartialOK, 0));
+       }
+
+       BOOL Scroll(SIZE size)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SCROLL, size.cx, size.cy);
+       }
+
+       BOOL RedrawItems(int nFirst, int nLast)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_REDRAWITEMS, nFirst, nLast);
+       }
+
+       BOOL Arrange(UINT nCode)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_ARRANGE, nCode, 0L);
+       }
+
+       CEdit EditLabel(int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CEdit((HWND)::SendMessage(m_hWnd, LVM_EDITLABEL, nItem, 0L));
+       }
+
+       BOOL Update(int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_UPDATE, nItem, 0L);
+       }
+
+       BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMS, (WPARAM)lParamSort, (LPARAM)pfnCompare);
+       }
+
+       CImageList RemoveImageList(int nImageList)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, (WPARAM)nImageList, NULL));
+       }
+
+       CImageList CreateDragImage(int nItem, LPPOINT lpPoint)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_CREATEDRAGIMAGE, nItem, (LPARAM)lpPoint));
+       }
+
+       DWORD ApproximateViewRect(int cx = -1, int cy = -1, int nCount = -1)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, LVM_APPROXIMATEVIEWRECT, nCount, MAKELPARAM(cx, cy));
+       }
+
+       int SubItemHitTest(LPLVHITTESTINFO lpInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, 0, (LPARAM)lpInfo);
+       }
+
+       int AddColumn(LPCTSTR strItem, int nItem, int nSubItem = -1,
+                       int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
+                       int nFmt = LVCFMT_LEFT)
+       {
+               const int cxOffset = 15;
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVCOLUMN lvc = { 0 };
+               lvc.mask = nMask;
+               lvc.fmt = nFmt;
+               lvc.pszText = (LPTSTR)strItem;
+               lvc.cx = GetStringWidth(lvc.pszText) + cxOffset;
+               if(nMask & LVCF_SUBITEM)
+                       lvc.iSubItem = (nSubItem != -1) ? nSubItem : nItem;
+               return InsertColumn(nItem, &lvc);
+       }
+
+       int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -1)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVITEM lvItem = { 0 };
+               lvItem.mask = LVIF_TEXT;
+               lvItem.iItem = nItem;
+               lvItem.iSubItem = nSubItem;
+               lvItem.pszText = (LPTSTR)strItem;
+               if(nImageIndex != -1)
+               {
+                       lvItem.mask |= LVIF_IMAGE;
+                       lvItem.iImage = nImageIndex;
+               }
+               if(nSubItem == 0)
+                       return InsertItem(&lvItem);
+               return SetItem(&lvItem) ? nItem : -1;
+       }
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMSEX, (WPARAM)lParamSort, (LPARAM)pfnCompare);
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+#if (_WIN32_WINNT >= 0x0501)
+       int InsertGroup(int nItem, PLVGROUP pGroup)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_INSERTGROUP, nItem, (LPARAM)pGroup);
+       }
+
+       int AddGroup(PLVGROUP pGroup)
+       {
+               return InsertGroup(-1, pGroup);
+       }
+
+       int RemoveGroup(int nGroupID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_REMOVEGROUP, nGroupID, 0L);
+       }
+
+       void MoveGroup(int nGroupID, int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_MOVEGROUP, nGroupID, nItem);
+       }
+
+       void MoveItemToGroup(int nItem, int nGroupID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_MOVEITEMTOGROUP, nItem, nGroupID);
+       }
+
+       int EnableGroupView(BOOL bEnable)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_ENABLEGROUPVIEW, bEnable, 0L);
+       }
+
+       int SortGroups(PFNLVGROUPCOMPARE pCompareFunc, LPVOID lpVoid = NULL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_SORTGROUPS, (WPARAM)pCompareFunc, (LPARAM)lpVoid);
+       }
+
+       void InsertGroupSorted(PLVINSERTGROUPSORTED pInsertGroupSorted)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_INSERTGROUPSORTED, (WPARAM)pInsertGroupSorted, 0L);
+       }
+
+       void RemoveAllGroups()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_REMOVEALLGROUPS, 0, 0L);
+       }
+
+       BOOL HasGroup(int nGroupID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_HASGROUP, nGroupID, 0L);
+       }
+
+       BOOL InsertMarkHitTest(LPPOINT lpPoint, LPLVINSERTMARK pInsertMark) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)pInsertMark);
+       }
+
+       BOOL SetInfoTip(PLVSETINFOTIP pSetInfoTip)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LVM_SETINFOTIP, 0, (LPARAM)pSetInfoTip);
+       }
+
+       void CancelEditLabel()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, LVM_CANCELEDITLABEL, 0, 0L);
+       }
+
+       UINT MapIndexToID(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, LVM_MAPINDEXTOID, nIndex, 0L);
+       }
+
+       int MapIDToIndex(UINT uID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_MAPIDTOINDEX, uID, 0L);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+#if (_WIN32_WINNT >= 0x0600)
+       int HitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
+       }
+
+       int HitTestEx(POINT pt, UINT* pFlags) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LVHITTESTINFO hti = { 0 };
+               hti.pt = pt;
+               int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)&hti);
+               if (pFlags != NULL)
+                       *pFlags = hti.flags;
+               return nRes;
+       }
+
+       int SubItemHitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+       // single-selection only
+       BOOL SelectItem(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0);
+
+               BOOL bRet = SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
+               if(bRet)
+                       bRet = EnsureVisible(nIndex, FALSE);
+               return bRet;
+       }
+};
+
+typedef CListViewCtrlT<ATL::CWindow>   CListViewCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTreeViewCtrl
+
+template <class TBase>
+class CTreeViewCtrlT : public TBase
+{
+public:
+// Constructors
+       CTreeViewCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CTreeViewCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_TREEVIEW;
+       }
+
+       UINT GetCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, TVM_GETCOUNT, 0, 0L);
+       }
+
+       UINT GetIndent() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, TVM_GETINDENT, 0, 0L);
+       }
+
+       void SetIndent(UINT nIndent)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TVM_SETINDENT, nIndent, 0L);
+       }
+
+       CImageList GetImageList(int nImageListType = TVSIL_NORMAL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_GETIMAGELIST, (WPARAM)nImageListType, 0L));
+       }
+
+       CImageList SetImageList(HIMAGELIST hImageList, int nImageListType = TVSIL_NORMAL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageListType, (LPARAM)hImageList));
+       }
+
+       BOOL GetItem(LPTVITEM pItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem);
+       }
+
+       BOOL SetItem(LPTVITEM pItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem);
+       }
+
+       BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage,
+               int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVITEM item = { 0 };
+               item.hItem = hItem;
+               item.mask = nMask;
+               item.pszText = (LPTSTR) lpszItem;
+               item.iImage = nImage;
+               item.iSelectedImage = nSelectedImage;
+               item.state = nState;
+               item.stateMask = nStateMask;
+               item.lParam = lParam;
+               return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)&item);
+       }
+
+       BOOL GetItemText(HTREEITEM hItem, LPTSTR lpstrText, int nLen) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpstrText != NULL);
+
+               TVITEM item = { 0 };
+               item.hItem = hItem;
+               item.mask = TVIF_TEXT;
+               item.pszText = lpstrText;
+               item.cchTextMax = nLen;
+
+               return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
+       }
+
+#ifndef _ATL_NO_COM
+       BOOL GetItemText(HTREEITEM hItem, BSTR& bstrText) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(bstrText == NULL);
+               TVITEM item = { 0 };
+               item.hItem = hItem;
+               item.mask = TVIF_TEXT;
+
+               LPTSTR lpstrText = NULL;
+               BOOL bRet = FALSE;
+               for(int nLen = 256; ; nLen *= 2)
+               {
+                       ATLTRY(lpstrText = new TCHAR[nLen]);
+                       if(lpstrText == NULL)
+                               break;
+                       lpstrText[0] = NULL;
+                       item.pszText = lpstrText;
+                       item.cchTextMax = nLen;
+                       bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
+                       if(!bRet || (lstrlen(item.pszText) < nLen - 1))
+                               break;
+                       delete [] lpstrText;
+                       lpstrText = NULL;
+               }
+
+               if(lpstrText != NULL)
+               {
+                       if(bRet)
+                               bstrText = ::SysAllocString(T2OLE(lpstrText));
+                       delete [] lpstrText;
+               }
+
+               return (bstrText != NULL) ? TRUE : FALSE;
+       }
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       BOOL GetItemText(HTREEITEM hItem, _CSTRING_NS::CString& strText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVITEM item = { 0 };
+               item.hItem = hItem;
+               item.mask = TVIF_TEXT;
+
+               strText.Empty();
+               BOOL bRet = FALSE;
+               for(int nLen = 256; ; nLen *= 2)
+               {
+                       item.pszText = strText.GetBufferSetLength(nLen);
+                       if(item.pszText == NULL)
+                       {
+                               bRet = FALSE;
+                               break;
+                       }
+                       item.cchTextMax = nLen;
+                       bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
+                       if(!bRet || (lstrlen(item.pszText) < nLen - 1))
+                               break;
+               }
+               strText.ReleaseBuffer();
+               return bRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       BOOL SetItemText(HTREEITEM hItem, LPCTSTR lpszItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItem(hItem, TVIF_TEXT, lpszItem, 0, 0, 0, 0, NULL);
+       }
+
+       BOOL GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVITEM item = { 0 };
+               item.hItem = hItem;
+               item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+               BOOL bRes = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
+               if (bRes)
+               {
+                       nImage = item.iImage;
+                       nSelectedImage = item.iSelectedImage;
+               }
+               return bRes;
+       }
+
+       BOOL SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItem(hItem, TVIF_IMAGE|TVIF_SELECTEDIMAGE, NULL, nImage, nSelectedImage, 0, 0, NULL);
+       }
+
+       UINT GetItemState(HTREEITEM hItem, UINT nStateMask) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+               return (((UINT)::SendMessage(m_hWnd, TVM_GETITEMSTATE, (WPARAM)hItem, (LPARAM)nStateMask)) & nStateMask);
+#else // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE))
+               TVITEM item = { 0 };
+               item.hItem = hItem;
+               item.mask = TVIF_STATE;
+               item.state = 0;
+               item.stateMask = nStateMask;
+               ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
+               return (item.state & nStateMask);
+#endif // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE))
+       }
+
+       BOOL SetItemState(HTREEITEM hItem, UINT nState, UINT nStateMask)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItem(hItem, TVIF_STATE, NULL, 0, 0, nState, nStateMask, NULL);
+       }
+
+       DWORD_PTR GetItemData(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVITEM item = { 0 };
+               item.hItem = hItem;
+               item.mask = TVIF_PARAM;
+               BOOL bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
+               return (DWORD_PTR)(bRet ? item.lParam : NULL);
+       }
+
+       BOOL SetItemData(HTREEITEM hItem, DWORD_PTR dwData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItem(hItem, TVIF_PARAM, NULL, 0, 0, 0, 0, (LPARAM)dwData);
+       }
+
+       CEdit GetEditControl() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CEdit((HWND)::SendMessage(m_hWnd, TVM_GETEDITCONTROL, 0, 0L));
+       }
+
+       UINT GetVisibleCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, TVM_GETVISIBLECOUNT, 0, 0L);
+       }
+
+       BOOL GetItemRect(HTREEITEM hItem, LPRECT lpRect, BOOL bTextOnly) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               *(HTREEITEM*)lpRect = hItem;
+               return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMRECT, (WPARAM)bTextOnly, (LPARAM)lpRect);
+       }
+
+       BOOL ItemHasChildren(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVITEM item = { 0 };
+               item.hItem = hItem;
+               item.mask = TVIF_CHILDREN;
+               ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
+               return item.cChildren;
+       }
+
+#ifndef _WIN32_WCE
+       CToolTipCtrl GetToolTips() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_GETTOOLTIPS, 0, 0L));
+       }
+
+       CToolTipCtrl SetToolTips(HWND hWndTT)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
+       }
+#endif // !_WIN32_WCE
+
+       int GetISearchString(LPTSTR lpstr) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
+       }
+
+       // checkboxes only
+       BOOL GetCheckState(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & TVS_CHECKBOXES) != 0);
+               UINT uRet = GetItemState(hItem, TVIS_STATEIMAGEMASK);
+               return (uRet >> 12) - 1;
+       }
+
+       BOOL SetCheckState(HTREEITEM hItem, BOOL bCheck)
+       {
+               int nCheck = bCheck ? 2 : 1;   // one based index
+               return SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nCheck), TVIS_STATEIMAGEMASK);
+       }
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       COLORREF GetBkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TVM_GETBKCOLOR, 0, 0L);
+       }
+
+       COLORREF SetBkColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TVM_SETBKCOLOR, 0, (LPARAM)clr);
+       }
+
+       COLORREF GetInsertMarkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TVM_GETINSERTMARKCOLOR, 0, 0L);
+       }
+
+       COLORREF SetInsertMarkColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TVM_SETINSERTMARKCOLOR, 0, (LPARAM)clr);
+       }
+
+       int GetItemHeight() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TVM_GETITEMHEIGHT, 0, 0L);
+       }
+
+       int SetItemHeight(int cyHeight)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TVM_SETITEMHEIGHT, cyHeight, 0L);
+       }
+
+       int GetScrollTime() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TVM_GETSCROLLTIME, 0, 0L);
+       }
+
+       int SetScrollTime(int nScrollTime)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TVM_SETSCROLLTIME, nScrollTime, 0L);
+       }
+
+       COLORREF GetTextColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TVM_GETTEXTCOLOR, 0, 0L);
+       }
+
+       COLORREF SetTextColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TVM_SETTEXTCOLOR, 0, (LPARAM)clr);
+       }
+
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       COLORREF GetLineColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TVM_GETLINECOLOR, 0, 0L);
+       }
+
+       COLORREF SetLineColor(COLORREF clrNew /*= CLR_DEFAULT*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TVM_SETLINECOLOR, 0, (LPARAM)clrNew);
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       BOOL GetItem(LPTVITEMEX pItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem);
+       }
+
+       BOOL SetItem(LPTVITEMEX pItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem);
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+       DWORD GetExtendedStyle() const
+       {
+#ifndef TVM_GETEXTENDEDSTYLE
+               const UINT TVM_GETEXTENDEDSTYLE = (TV_FIRST + 45);
+#endif
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TVM_GETEXTENDEDSTYLE, 0, 0L);
+       }
+
+       DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask)
+       {
+#ifndef TVM_SETEXTENDEDSTYLE
+               const UINT TVM_SETEXTENDEDSTYLE = (TV_FIRST + 44);
+#endif
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TVM_SETEXTENDEDSTYLE, dwMask, dwStyle);
+       }
+
+#if (_WIN32_WINNT >= 0x0600)
+       BOOL SetAutoScrollInfo(UINT uPixPerSec, UINT uUpdateTime)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SETAUTOSCROLLINFO, (WPARAM)uPixPerSec, (LPARAM)uUpdateTime);
+       }
+
+       DWORD GetSelectedCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TVM_GETSELECTEDCOUNT, 0, 0L);
+       }
+
+       BOOL GetItemPartRect(HTREEITEM hItem, TVITEMPART partID, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVGETITEMPARTRECTINFO gipri = { hItem, lpRect, partID };
+               return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMPARTRECT, 0, (LPARAM)&gipri);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+// Operations
+       HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsertStruct)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct);
+       }
+
+       HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage,
+               int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter); 
+       }
+
+       HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter);
+       }
+
+       HTREEITEM InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
+               int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
+               HTREEITEM hParent, HTREEITEM hInsertAfter)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVINSERTSTRUCT tvis = { 0 };
+               tvis.hParent = hParent;
+               tvis.hInsertAfter = hInsertAfter;
+               tvis.item.mask = nMask;
+               tvis.item.pszText = (LPTSTR) lpszItem;
+               tvis.item.iImage = nImage;
+               tvis.item.iSelectedImage = nSelectedImage;
+               tvis.item.state = nState;
+               tvis.item.stateMask = nStateMask;
+               tvis.item.lParam = lParam;
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
+       }
+
+       BOOL DeleteItem(HTREEITEM hItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)hItem);
+       }
+
+       BOOL DeleteAllItems()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
+       }
+
+       BOOL Expand(HTREEITEM hItem, UINT nCode = TVE_EXPAND)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_EXPAND, nCode, (LPARAM)hItem);
+       }
+
+       HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem);
+       }
+
+       HTREEITEM GetChildItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+       }
+
+       HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem); 
+       }
+
+       HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem);
+       }
+
+       HTREEITEM GetParentItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem); 
+       }
+
+       HTREEITEM GetFirstVisibleItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L);
+       }
+
+       HTREEITEM GetNextVisibleItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem);
+       }
+
+       HTREEITEM GetPrevVisibleItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem);
+       }
+
+       HTREEITEM GetSelectedItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L);
+       }
+
+       HTREEITEM GetDropHilightItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L);
+       }
+
+       HTREEITEM GetRootItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L);
+       }
+
+#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
+       HTREEITEM GetLastVisibleItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
+       }
+#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0600)
+       HTREEITEM GetNextSelectedItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0600)
+
+       BOOL Select(HTREEITEM hItem, UINT nCode)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, nCode, (LPARAM)hItem);
+       }
+
+       BOOL SelectItem(HTREEITEM hItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem);
+       }
+
+       BOOL SelectDropTarget(HTREEITEM hItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)hItem);
+       }
+
+       BOOL SelectSetFirstVisible(HTREEITEM hItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hItem);
+       }
+
+       CEdit EditLabel(HTREEITEM hItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CEdit((HWND)::SendMessage(m_hWnd, TVM_EDITLABEL, 0, (LPARAM)hItem));
+       }
+
+       BOOL EndEditLabelNow(BOOL bCancel)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_ENDEDITLABELNOW, bCancel, 0L);
+       }
+
+       HTREEITEM HitTest(TVHITTESTINFO* pHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo);
+       }
+
+       HTREEITEM HitTest(POINT pt, UINT* pFlags) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVHITTESTINFO hti = { 0 };
+               hti.pt = pt;
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti);
+               if (pFlags != NULL)
+                       *pFlags = hti.flags;
+               return hTreeItem;
+       }
+
+       BOOL SortChildren(HTREEITEM hItem, BOOL bRecurse = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDREN, (WPARAM)bRecurse, (LPARAM)hItem);
+       }
+
+       BOOL EnsureVisible(HTREEITEM hItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_ENSUREVISIBLE, 0, (LPARAM)hItem);
+       }
+
+       BOOL SortChildrenCB(LPTVSORTCB pSort, BOOL bRecurse = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDRENCB, (WPARAM)bRecurse, (LPARAM)pSort);
+       }
+
+       CImageList RemoveImageList(int nImageList)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageList, NULL));
+       }
+
+       CImageList CreateDragImage(HTREEITEM hItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItem));
+       }
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       BOOL SetInsertMark(HTREEITEM hTreeItem, BOOL bAfter)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, bAfter, (LPARAM)hTreeItem);
+       }
+
+       BOOL RemoveInsertMark()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, 0, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+#if (_WIN32_WINNT >= 0x0501)
+       HTREEITEM MapAccIDToHTREEITEM(UINT uID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L);
+       }
+
+       UINT MapHTREEITEMToAccID(HTREEITEM hTreeItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, TVM_MAPHTREEITEMTOACCID, (WPARAM)hTreeItem, 0L);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+#if (_WIN32_WINNT >= 0x0600)
+       void ShowInfoTip(HTREEITEM hItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TVM_SHOWINFOTIP, 0, (LPARAM)hItem);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+};
+
+typedef CTreeViewCtrlT<ATL::CWindow>   CTreeViewCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTreeViewCtrlEx
+
+// forward declaration
+template <class TBase> class CTreeViewCtrlExT;
+
+// Note: TBase here is for CTreeViewCtrlExT, and not for CTreeItemT itself
+template <class TBase>
+class CTreeItemT
+{
+public:
+       HTREEITEM m_hTreeItem;
+       CTreeViewCtrlExT<TBase>* m_pTreeView;
+
+// Construction
+       CTreeItemT(HTREEITEM hTreeItem = NULL, CTreeViewCtrlExT<TBase>* pTreeView = NULL) : m_hTreeItem(hTreeItem), m_pTreeView(pTreeView)
+       { }
+       CTreeItemT(const CTreeItemT<TBase>& posSrc)
+       {
+               *this = posSrc;
+       }
+
+       operator HTREEITEM() { return m_hTreeItem; }
+
+       CTreeItemT<TBase>& operator =(const CTreeItemT<TBase>& itemSrc)
+       {
+               m_hTreeItem = itemSrc.m_hTreeItem;
+               m_pTreeView = itemSrc.m_pTreeView;
+               return *this;
+       }
+
+// Attributes
+       CTreeViewCtrlExT<TBase>* GetTreeView() const { return m_pTreeView; }
+
+       BOOL operator !() const { return m_hTreeItem == NULL; }
+
+       BOOL IsNull() const { return m_hTreeItem == NULL; }
+       
+       BOOL GetRect(LPRECT lpRect, BOOL bTextOnly) const;
+       BOOL GetText(LPTSTR lpstrText, int nLen) const;
+#ifndef _ATL_NO_COM
+       BOOL GetText(BSTR& bstrText) const;
+#endif // !_ATL_NO_COM
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       BOOL GetText(_CSTRING_NS::CString& strText) const;
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       BOOL SetText(LPCTSTR lpszItem);
+       BOOL GetImage(int& nImage, int& nSelectedImage) const;
+       BOOL SetImage(int nImage, int nSelectedImage);
+       UINT GetState(UINT nStateMask) const;
+       BOOL SetState(UINT nState, UINT nStateMask);
+       DWORD_PTR GetData() const;
+       BOOL SetData(DWORD_PTR dwData);
+       BOOL SetItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam);
+
+// Operations
+       CTreeItemT<TBase> InsertAfter(LPCTSTR lpstrItem, HTREEITEM hItemAfter, int nImageIndex)
+       {
+               return _Insert(lpstrItem, nImageIndex, hItemAfter);
+       }
+
+       CTreeItemT<TBase> AddHead(LPCTSTR lpstrItem, int nImageIndex)
+       {
+               return _Insert(lpstrItem, nImageIndex, TVI_FIRST);
+       }
+
+       CTreeItemT<TBase> AddTail(LPCTSTR lpstrItem, int nImageIndex)
+       {
+               return _Insert(lpstrItem, nImageIndex, TVI_LAST);
+       }
+
+       CTreeItemT<TBase> GetChild() const;
+       CTreeItemT<TBase> GetNext(UINT nCode) const;
+       CTreeItemT<TBase> GetNextSibling() const;
+       CTreeItemT<TBase> GetPrevSibling() const;
+       CTreeItemT<TBase> GetParent() const;
+       CTreeItemT<TBase> GetFirstVisible() const;
+       CTreeItemT<TBase> GetNextVisible() const;
+       CTreeItemT<TBase> GetPrevVisible() const;
+       CTreeItemT<TBase> GetSelected() const;
+       CTreeItemT<TBase> GetDropHilight() const;
+       CTreeItemT<TBase> GetRoot() const;
+#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
+       CTreeItemT<TBase> GetLastVisible() const;
+#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
+#if (_WIN32_IE >= 0x0600)
+       CTreeItemT<TBase> GetNextSelected() const;
+#endif // (_WIN32_IE >= 0x0600)
+       BOOL HasChildren() const;
+       BOOL Delete();
+       BOOL Expand(UINT nCode = TVE_EXPAND);
+       BOOL Select(UINT nCode);
+       BOOL Select();
+       BOOL SelectDropTarget();
+       BOOL SelectSetFirstVisible();
+       HWND EditLabel();
+       HIMAGELIST CreateDragImage();
+       BOOL SortChildren(BOOL bRecurse = FALSE);
+       BOOL EnsureVisible();
+       CTreeItemT<TBase> _Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter);
+       int GetImageIndex() const;
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       BOOL SetInsertMark(BOOL bAfter);
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+#if (_WIN32_WINNT >= 0x0501)
+       UINT MapHTREEITEMToAccID() const;
+#endif // (_WIN32_WINNT >= 0x0501)
+#if (_WIN32_WINNT >= 0x0600)
+       void ShowInfoTip();
+       BOOL GetPartRect(TVITEMPART partID, LPRECT lpRect) const;
+#endif // (_WIN32_WINNT >= 0x0600)
+};
+
+typedef CTreeItemT<ATL::CWindow>   CTreeItem;
+
+
+template <class TBase>
+class CTreeViewCtrlExT : public CTreeViewCtrlT< TBase >
+{
+public:
+// Constructors
+       CTreeViewCtrlExT(HWND hWnd = NULL) : CTreeViewCtrlT< TBase >(hWnd)
+       { }
+
+       CTreeViewCtrlExT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Operations (overides that return CTreeItem)
+       CTreeItemT<TBase> InsertItem(LPTVINSERTSTRUCT lpInsertStruct)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct);
+               return CTreeItemT<TBase>(hTreeItem, this);
+       }
+
+       CTreeItemT<TBase> InsertItem(LPCTSTR lpszItem, int nImage,
+               int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter); 
+       }
+
+       CTreeItemT<TBase> InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter);
+       }
+
+       CTreeItemT<TBase> GetNextItem(HTREEITEM hItem, UINT nCode) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetChildItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this); 
+       }
+
+       CTreeItemT<TBase> GetNextSiblingItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem); 
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetPrevSiblingItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetParentItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem); 
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetFirstVisibleItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd)); 
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetNextVisibleItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetPrevVisibleItem(HTREEITEM hItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetSelectedItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetDropHilightItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> GetRootItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
+       CTreeItemT<TBase> GetLastVisibleItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0600)
+       CTreeItemT<TBase> GetNextSelectedItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+#endif // (_WIN32_IE >= 0x0600)
+
+       CTreeItemT<TBase> HitTest(TVHITTESTINFO* pHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+       CTreeItemT<TBase> InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
+               int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
+               HTREEITEM hParent, HTREEITEM hInsertAfter)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVINSERTSTRUCT tvis = { 0 };
+               tvis.hParent = hParent;
+               tvis.hInsertAfter = hInsertAfter;
+               tvis.item.mask = nMask;
+               tvis.item.pszText = (LPTSTR) lpszItem;
+               tvis.item.iImage = nImage;
+               tvis.item.iSelectedImage = nSelectedImage;
+               tvis.item.state = nState;
+               tvis.item.stateMask = nStateMask;
+               tvis.item.lParam = lParam;
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
+               return CTreeItemT<TBase>(hTreeItem, this);
+       }
+
+       CTreeItemT<TBase> HitTest(POINT pt, UINT* pFlags) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TVHITTESTINFO hti = { 0 };
+               hti.pt = pt;
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti);
+               if (pFlags != NULL)
+                       *pFlags = hti.flags;
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+
+#if (_WIN32_WINNT >= 0x0501)
+       CTreeItemT<TBase> MapAccIDToHTREEITEM(UINT uID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L);
+               return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+};
+
+typedef CTreeViewCtrlExT<ATL::CWindow>   CTreeViewCtrlEx;
+
+
+// CTreeItem inline methods
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::GetRect(LPRECT lpRect, BOOL bTextOnly) const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetItemRect(m_hTreeItem,lpRect,bTextOnly);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNext(UINT nCode) const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetNextItem(m_hTreeItem,nCode);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetChild() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetChildItem(m_hTreeItem);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextSibling() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetNextSiblingItem(m_hTreeItem);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetPrevSibling() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetPrevSiblingItem(m_hTreeItem);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetParent() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetParentItem(m_hTreeItem);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetFirstVisible() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetFirstVisibleItem();
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextVisible() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetNextVisibleItem(m_hTreeItem);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetPrevVisible() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetPrevVisibleItem(m_hTreeItem);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetSelected() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetSelectedItem();
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetDropHilight() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetDropHilightItem();
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetRoot() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetRootItem();
+}
+
+#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetLastVisible() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetLastVisibleItem();
+}
+#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0600)
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextSelected() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetNextSelectedItem();
+}
+#endif // (_WIN32_IE >= 0x0600)
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::GetText(LPTSTR lpstrText, int nLen) const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetItemText(m_hTreeItem, lpstrText, nLen);
+}
+
+#ifndef _ATL_NO_COM
+#ifdef _OLEAUTO_H_
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::GetText(BSTR& bstrText) const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetItemText(m_hTreeItem, bstrText);
+}
+#endif // _OLEAUTO_H_
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::GetText(_CSTRING_NS::CString& strText) const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetItemText(m_hTreeItem, strText);
+}
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::GetImage(int& nImage, int& nSelectedImage) const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetItemImage(m_hTreeItem,nImage,nSelectedImage);
+}
+
+template <class TBase>
+inline UINT CTreeItemT<TBase>::GetState(UINT nStateMask) const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetItemState(m_hTreeItem,nStateMask);
+}
+
+template <class TBase>
+inline DWORD_PTR CTreeItemT<TBase>::GetData() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetItemData(m_hTreeItem);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SetItem(UINT nMask, LPCTSTR lpszItem, int nImage,
+               int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SetItem(m_hTreeItem, nMask, lpszItem, nImage, nSelectedImage, nState, nStateMask, lParam);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SetText(LPCTSTR lpszItem)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SetItemText(m_hTreeItem,lpszItem);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SetImage(int nImage, int nSelectedImage)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SetItemImage(m_hTreeItem,nImage,nSelectedImage);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SetState(UINT nState, UINT nStateMask)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SetItemState(m_hTreeItem,nState,nStateMask);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SetData(DWORD_PTR dwData)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SetItemData(m_hTreeItem,dwData);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::HasChildren() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->ItemHasChildren(m_hTreeItem);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::Delete()
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->DeleteItem(m_hTreeItem);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::Expand(UINT nCode /*= TVE_EXPAND*/)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->Expand(m_hTreeItem,nCode);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::Select(UINT nCode)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->Select(m_hTreeItem,nCode);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::Select()
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SelectItem(m_hTreeItem);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SelectDropTarget()
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SelectDropTarget(m_hTreeItem);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SelectSetFirstVisible()
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SelectSetFirstVisible(m_hTreeItem);
+}
+
+template <class TBase>
+inline HWND CTreeItemT<TBase>::EditLabel()
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->EditLabel(m_hTreeItem);
+}
+
+template <class TBase>
+inline HIMAGELIST CTreeItemT<TBase>::CreateDragImage()
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->CreateDragImage(m_hTreeItem);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SortChildren(BOOL bRecurse /*= FALSE*/)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SortChildren(m_hTreeItem, bRecurse);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::EnsureVisible()
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->EnsureVisible(m_hTreeItem);
+}
+
+template <class TBase>
+inline CTreeItemT<TBase> CTreeItemT<TBase>::_Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       TVINSERTSTRUCT ins = { 0 };
+       ins.hParent = m_hTreeItem;
+       ins.hInsertAfter = hItemAfter;
+       ins.item.mask = TVIF_TEXT;
+       ins.item.pszText = (LPTSTR)lpstrItem;
+       if(nImageIndex != -1)
+       {
+               ins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+               ins.item.iImage = nImageIndex;
+               ins.item.iSelectedImage = nImageIndex;
+       }
+       return CTreeItemT<TBase>(m_pTreeView->InsertItem(&ins), m_pTreeView);
+}
+
+template <class TBase>
+inline int CTreeItemT<TBase>::GetImageIndex() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       TVITEM item = { 0 };
+       item.mask = TVIF_HANDLE | TVIF_IMAGE;
+       item.hItem = m_hTreeItem;
+       m_pTreeView->GetItem(&item);
+       return item.iImage;
+}
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::SetInsertMark(BOOL bAfter)
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->SetInsertMark(m_hTreeItem, bAfter);
+}
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+#if (_WIN32_WINNT >= 0x0501)
+template <class TBase>
+inline UINT CTreeItemT<TBase>::MapHTREEITEMToAccID() const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->MapHTREEITEMToAccID(m_hTreeItem);
+}
+#endif // (_WIN32_WINNT >= 0x0501)
+
+#if (_WIN32_WINNT >= 0x0600)
+template <class TBase>
+inline void CTreeItemT<TBase>::ShowInfoTip()
+{
+       ATLASSERT(m_pTreeView != NULL);
+       m_pTreeView->ShowInfoTip(m_hTreeItem);
+}
+
+template <class TBase>
+inline BOOL CTreeItemT<TBase>::GetPartRect(TVITEMPART partID, LPRECT lpRect) const
+{
+       ATLASSERT(m_pTreeView != NULL);
+       return m_pTreeView->GetItemPartRect(m_hTreeItem, partID, lpRect);
+}
+#endif // (_WIN32_WINNT >= 0x0600)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CToolBarCtrl
+
+template <class TBase>
+class CToolBarCtrlT : public TBase
+{
+public:
+// Construction
+       CToolBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CToolBarCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return TOOLBARCLASSNAME;
+       }
+
+       BOOL IsButtonEnabled(int nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONENABLED, nID, 0L);
+       }
+
+       BOOL IsButtonChecked(int nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONCHECKED, nID, 0L);
+       }
+
+       BOOL IsButtonPressed(int nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONPRESSED, nID, 0L);
+       }
+
+       BOOL IsButtonHidden(int nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return(BOOL) ::SendMessage(m_hWnd, TB_ISBUTTONHIDDEN, nID, 0L);
+       }
+
+       BOOL IsButtonIndeterminate(int nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONINDETERMINATE, nID, 0L);
+       }
+
+       int GetState(int nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_GETSTATE, nID, 0L);
+       }
+
+       BOOL SetState(int nID, UINT nState)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETSTATE, nID, MAKELPARAM(nState, 0));
+       }
+
+       BOOL GetButton(int nIndex, LPTBBUTTON lpButton) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_GETBUTTON, nIndex, (LPARAM)lpButton);
+       }
+
+       int GetButtonCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_BUTTONCOUNT, 0, 0L);
+       }
+
+       BOOL GetItemRect(int nIndex, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_GETITEMRECT, nIndex, (LPARAM)lpRect);
+       }
+
+       void SetButtonStructSize(int nSize = sizeof(TBBUTTON))
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_BUTTONSTRUCTSIZE, nSize, 0L);
+       }
+
+       BOOL SetButtonSize(SIZE size)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(size.cx, size.cy));
+       }
+
+       BOOL SetButtonSize(int cx, int cy)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, cy));
+       }
+
+       BOOL SetBitmapSize(SIZE size)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(size.cx, size.cy));
+       }
+
+       BOOL SetBitmapSize(int cx, int cy)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(cx, cy));
+       }
+
+#ifndef _WIN32_WCE
+       CToolTipCtrl GetToolTips() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TB_GETTOOLTIPS, 0, 0L));
+       }
+
+       void SetToolTips(HWND hWndToolTip)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       void SetNotifyWnd(HWND hWnd)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_SETPARENT, (WPARAM)hWnd, 0L);
+       }
+
+       int GetRows() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_GETROWS, 0, 0L);
+       }
+
+       void SetRows(int nRows, BOOL bLarger, LPRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_SETROWS, MAKELPARAM(nRows, bLarger), (LPARAM)lpRect);
+       }
+
+       BOOL SetCmdID(int nIndex, UINT nID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETCMDID, nIndex, nID);
+       }
+
+       DWORD GetBitmapFlags() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TB_GETBITMAPFLAGS, 0, 0L);
+       }
+
+       int GetBitmap(int nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_GETBITMAP, nID, 0L);
+       }
+
+       int GetButtonText(int nID, LPTSTR lpstrText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_GETBUTTONTEXT, nID, (LPARAM)lpstrText);
+       }
+
+       // nIndex - IE5 or higher only
+       CImageList GetImageList(int nIndex = 0) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETIMAGELIST, nIndex, 0L));
+       }
+
+       // nIndex - IE5 or higher only
+       CImageList SetImageList(HIMAGELIST hImageList, int nIndex = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETIMAGELIST, nIndex, (LPARAM)hImageList));
+       }
+
+       // nIndex - IE5 or higher only
+       CImageList GetDisabledImageList(int nIndex = 0) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETDISABLEDIMAGELIST, nIndex, 0L));
+       }
+
+       // nIndex - IE5 or higher only
+       CImageList SetDisabledImageList(HIMAGELIST hImageList, int nIndex = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETDISABLEDIMAGELIST, nIndex, (LPARAM)hImageList));
+       }
+
+#ifndef _WIN32_WCE
+       // nIndex - IE5 or higher only
+       CImageList GetHotImageList(int nIndex = 0) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETHOTIMAGELIST, nIndex, 0L));
+       }
+
+       // nIndex - IE5 or higher only
+       CImageList SetHotImageList(HIMAGELIST hImageList, int nIndex = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETHOTIMAGELIST, nIndex, (LPARAM)hImageList));
+       }
+#endif // !_WIN32_WCE
+
+       DWORD GetStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TB_GETSTYLE, 0, 0L);
+       }
+
+       void SetStyle(DWORD dwStyle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_SETSTYLE, 0, dwStyle);
+       }
+
+       DWORD GetButtonSize() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TB_GETBUTTONSIZE, 0, 0L);
+       }
+
+       void GetButtonSize(SIZE& size) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_GETBUTTONSIZE, 0, 0L);
+               size.cx = LOWORD(dwRet);
+               size.cy = HIWORD(dwRet);
+       }
+
+       BOOL GetRect(int nID, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_GETRECT, nID, (LPARAM)lpRect);
+       }
+
+       int GetTextRows() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_GETTEXTROWS, 0, 0L);
+       }
+
+       BOOL SetButtonWidth(int cxMin, int cxMax)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONWIDTH, 0, MAKELPARAM(cxMin, cxMax));
+       }
+
+       BOOL SetIndent(int nIndent)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETINDENT, nIndent, 0L);
+       }
+
+       BOOL SetMaxTextRows(int nMaxTextRows)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, nMaxTextRows, 0L);
+       }
+
+#if (_WIN32_IE >= 0x0400)
+#ifndef _WIN32_WCE
+       BOOL GetAnchorHighlight() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_GETANCHORHIGHLIGHT, 0, 0L);
+       }
+
+       BOOL SetAnchorHighlight(BOOL bEnable = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETANCHORHIGHLIGHT, bEnable, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       int GetButtonInfo(int nID, LPTBBUTTONINFO lptbbi) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_GETBUTTONINFO, nID, (LPARAM)lptbbi);
+       }
+
+       BOOL SetButtonInfo(int nID, LPTBBUTTONINFO lptbbi)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)lptbbi);
+       }
+
+       BOOL SetButtonInfo(int nID, DWORD dwMask, BYTE Style, BYTE State, LPCTSTR lpszItem, 
+                          int iImage, WORD cx, int iCommand, DWORD_PTR lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TBBUTTONINFO tbbi = { 0 };
+               tbbi.cbSize = sizeof(TBBUTTONINFO);
+               tbbi.dwMask = dwMask;
+               tbbi.idCommand = iCommand;
+               tbbi.iImage = iImage;
+               tbbi.fsState = State;
+               tbbi.fsStyle = Style;
+               tbbi.cx = cx;
+               tbbi.pszText = (LPTSTR) lpszItem;
+               tbbi.lParam = lParam;
+               return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)&tbbi);
+       }
+
+#ifndef _WIN32_WCE
+       int GetHotItem() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_GETHOTITEM, 0, 0L);
+       }
+
+       int SetHotItem(int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_SETHOTITEM, nItem, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL IsButtonHighlighted(int nButtonID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONHIGHLIGHTED, nButtonID, 0L);
+       }
+
+       DWORD SetDrawTextFlags(DWORD dwMask, DWORD dwFlags)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TB_SETDRAWTEXTFLAGS, dwMask, dwFlags);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetColorScheme(LPCOLORSCHEME lpcs) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_GETCOLORSCHEME, 0, (LPARAM)lpcs);
+       }
+
+       void SetColorScheme(LPCOLORSCHEME lpcs)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_SETCOLORSCHEME, 0, (LPARAM)lpcs);
+       }
+
+       DWORD GetExtendedStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TB_GETEXTENDEDSTYLE, 0, 0L);
+       }
+
+       DWORD SetExtendedStyle(DWORD dwStyle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, dwStyle);
+       }
+
+       void GetInsertMark(LPTBINSERTMARK lptbim) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_GETINSERTMARK, 0, (LPARAM)lptbim);
+       }
+
+       void SetInsertMark(LPTBINSERTMARK lptbim)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_SETINSERTMARK, 0, (LPARAM)lptbim);
+       }
+
+       COLORREF GetInsertMarkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TB_GETINSERTMARKCOLOR, 0, 0L);
+       }
+
+       COLORREF SetInsertMarkColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, TB_SETINSERTMARKCOLOR, 0, (LPARAM)clr);
+       }
+
+       BOOL GetMaxSize(LPSIZE lpSize) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_GETMAXSIZE, 0, (LPARAM)lpSize);
+       }
+
+       void GetPadding(LPSIZE lpSizePadding) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpSizePadding != NULL);
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_GETPADDING, 0, 0L);
+               lpSizePadding->cx = GET_X_LPARAM(dwRet);
+               lpSizePadding->cy = GET_Y_LPARAM(dwRet);
+       }
+
+       void SetPadding(int cx, int cy, LPSIZE lpSizePadding = NULL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_SETPADDING, 0, MAKELPARAM(cx, cy));
+               if(lpSizePadding != NULL)
+               {
+                       lpSizePadding->cx = GET_X_LPARAM(dwRet);
+                       lpSizePadding->cy = GET_Y_LPARAM(dwRet);
+               }
+       }
+
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // !_WIN32_WCE
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       int GetString(int nString, LPTSTR lpstrString, int cchMaxLen) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(cchMaxLen, nString), (LPARAM)lpstrString);
+       }
+
+       int GetStringBSTR(int nString, BSTR& bstrString) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(bstrString == NULL);
+               int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL));
+               if(nLength != -1)
+               {
+                       CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+                       LPTSTR lpstrText = buff.Allocate(nLength + 1);
+                       if(lpstrText != NULL)
+                       {
+                               nLength = (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstrText);
+                               if(nLength != -1)
+                                       bstrString = ::SysAllocString(T2OLE(lpstrText));
+                       }
+                       else
+                       {
+                               nLength = -1;
+                       }
+               }
+
+               return nLength;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       int GetString(int nString, _CSTRING_NS::CString& str) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL));
+               if(nLength != -1)
+               {
+                       LPTSTR lpstr = str.GetBufferSetLength(nLength + 1);
+                       if(lpstr != NULL)
+                               nLength = (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstr);
+                       else
+                               nLength = -1;
+                       str.ReleaseBuffer();
+               }
+               return nLength;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+#if (_WIN32_WINNT >= 0x0501)
+       void GetMetrics(LPTBMETRICS lptbm) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_GETMETRICS, 0, (LPARAM)lptbm);
+       }
+
+       void SetMetrics(LPTBMETRICS lptbm)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_SETMETRICS, 0, (LPARAM)lptbm);
+       }
+
+       void SetWindowTheme(LPCWSTR lpstrTheme)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+#if (_WIN32_WINNT >= 0x0600)
+       CImageList GetPressedImageList(int nIndex = 0) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETPRESSEDIMAGELIST, nIndex, 0L));
+       }
+
+       CImageList SetPressedImageList(HIMAGELIST hImageList, int nIndex = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETPRESSEDIMAGELIST, nIndex, (LPARAM)hImageList));
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+// Operations
+       BOOL EnableButton(int nID, BOOL bEnable = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_ENABLEBUTTON, nID, MAKELPARAM(bEnable, 0));
+       }
+
+       BOOL CheckButton(int nID, BOOL bCheck = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_CHECKBUTTON, nID, MAKELPARAM(bCheck, 0));
+       }
+
+       BOOL PressButton(int nID, BOOL bPress = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_PRESSBUTTON, nID, MAKELPARAM(bPress, 0));
+       }
+
+       BOOL HideButton(int nID, BOOL bHide = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_HIDEBUTTON, nID, MAKELPARAM(bHide, 0));
+       }
+
+       BOOL Indeterminate(int nID, BOOL bIndeterminate = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_INDETERMINATE, nID, MAKELPARAM(bIndeterminate, 0));
+       }
+
+       int AddBitmap(int nNumButtons, UINT nBitmapID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TBADDBITMAP tbab = { 0 };
+               tbab.hInst = ModuleHelper::GetResourceInstance();
+               ATLASSERT(tbab.hInst != NULL);
+               tbab.nID = nBitmapID;
+               return (int)::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab);
+       }
+
+       int AddBitmap(int nNumButtons, HBITMAP hBitmap)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TBADDBITMAP tbab = { 0 };
+               tbab.hInst = NULL;
+               tbab.nID = (UINT_PTR)hBitmap;
+               return (int)::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab);
+       }
+
+       BOOL AddButtons(int nNumButtons, LPTBBUTTON lpButtons)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_ADDBUTTONS, nNumButtons, (LPARAM)lpButtons);
+       }
+
+       BOOL InsertButton(int nIndex, LPTBBUTTON lpButton)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)lpButton);
+       }
+
+       BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap, 
+                         INT_PTR iString, DWORD_PTR lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TBBUTTON tbb = { 0 };
+               tbb.fsStyle = Style;
+               tbb.fsState = State;
+               tbb.idCommand = iCommand;
+               tbb.iBitmap = iBitmap;
+               tbb.iString = iString;
+               tbb.dwData = lParam;
+               return (BOOL)::SendMessage(m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)&tbb);
+       }
+
+       BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap, 
+                         LPCTSTR lpszItem, DWORD_PTR lParam)
+       {
+               return InsertButton(nIndex, iCommand, Style, State, iBitmap, (INT_PTR)lpszItem, lParam);
+       }
+
+       BOOL AddButton(LPTBBUTTON lpButton)
+       {
+               return InsertButton(-1, lpButton);
+       }
+
+       BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, INT_PTR iString, DWORD_PTR lParam)
+       {
+               return InsertButton(-1, iCommand, Style, State, iBitmap, iString, lParam);
+       }
+
+       BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, LPCTSTR lpszItem, DWORD_PTR lParam)
+       {
+               return InsertButton(-1, iCommand, Style, State, iBitmap, lpszItem, lParam);
+       }
+
+       BOOL DeleteButton(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_DELETEBUTTON, nIndex, 0L);
+       }
+
+       UINT CommandToIndex(UINT nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, TB_COMMANDTOINDEX, nID, 0L);
+       }
+
+#ifndef _WIN32_WCE
+       void SaveState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TBSAVEPARAMS tbs = { 0 };
+               tbs.hkr = hKeyRoot;
+               tbs.pszSubKey = lpszSubKey;
+               tbs.pszValueName = lpszValueName;
+               ::SendMessage(m_hWnd, TB_SAVERESTORE, (WPARAM)TRUE, (LPARAM)&tbs);
+       }
+
+       void RestoreState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TBSAVEPARAMS tbs = { 0 };
+               tbs.hkr = hKeyRoot;
+               tbs.pszSubKey = lpszSubKey;
+               tbs.pszValueName = lpszValueName;
+               ::SendMessage(m_hWnd, TB_SAVERESTORE, (WPARAM)FALSE, (LPARAM)&tbs);
+       }
+
+       void Customize()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_CUSTOMIZE, 0, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       int AddString(UINT nStringID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_ADDSTRING, (WPARAM)ModuleHelper::GetResourceInstance(), (LPARAM)nStringID);
+       }
+
+       int AddStrings(LPCTSTR lpszStrings)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_ADDSTRING, 0, (LPARAM)lpszStrings);
+       }
+
+       void AutoSize()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TB_AUTOSIZE, 0, 0L);
+       }
+
+       BOOL ChangeBitmap(int nID, int nBitmap)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_CHANGEBITMAP, nID, MAKELPARAM(nBitmap, 0));
+       }
+
+       int LoadImages(int nBitmapID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)ModuleHelper::GetResourceInstance());
+       }
+
+       int LoadStdImages(int nBitmapID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)HINST_COMMCTRL);
+       }
+
+       BOOL ReplaceBitmap(LPTBREPLACEBITMAP ptbrb)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_REPLACEBITMAP, 0, (LPARAM)ptbrb);
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       int HitTest(LPPOINT lpPoint) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TB_HITTEST, 0, (LPARAM)lpPoint);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL InsertMarkHitTest(LPPOINT lpPoint, LPTBINSERTMARK lptbim) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)lptbim);
+       }
+
+       BOOL InsertMarkHitTest(int x, int y, LPTBINSERTMARK lptbim) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               POINT pt = { x, y };
+               return (BOOL)::SendMessage(m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)&pt, (LPARAM)lptbim);
+       }
+
+       BOOL MapAccelerator(TCHAR chAccel, int& nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_MAPACCELERATOR, (WPARAM)chAccel, (LPARAM)&nID);
+       }
+
+       BOOL MarkButton(int nID, BOOL bHighlight = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_MARKBUTTON, nID, MAKELPARAM(bHighlight, 0));
+       }
+
+       BOOL MoveButton(int nOldPos, int nNewPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TB_MOVEBUTTON, nOldPos, nNewPos);
+       }
+
+       HRESULT GetObject(REFIID iid, LPVOID* ppvObject)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HRESULT)::SendMessage(m_hWnd, TB_GETOBJECT, (WPARAM)&iid, (LPARAM)ppvObject);
+       }
+#endif // !_WIN32_WCE
+#endif // (_WIN32_IE >= 0x0400)
+};
+
+typedef CToolBarCtrlT<ATL::CWindow>   CToolBarCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CStatusBarCtrl
+
+template <class TBase>
+class CStatusBarCtrlT : public TBase
+{
+public:
+// Constructors
+       CStatusBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CStatusBarCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Methods
+       static LPCTSTR GetWndClassName()
+       {
+               return STATUSCLASSNAME;
+       }
+
+       int GetParts(int nParts, int* pParts) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, SB_GETPARTS, nParts, (LPARAM)pParts);
+       }
+
+       BOOL SetParts(int nParts, int* pWidths)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, SB_SETPARTS, nParts, (LPARAM)pWidths);
+       }
+
+       int GetTextLength(int nPane, int* pType = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L);
+               if (pType != NULL)
+                       *pType = (int)(short)HIWORD(dwRet);
+               return (int)(short)LOWORD(dwRet);
+       }
+
+       int GetText(int nPane, LPTSTR lpszText, int* pType = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, SB_GETTEXT, (WPARAM)nPane, (LPARAM)lpszText);
+               if(pType != NULL)
+                       *pType = (int)(short)HIWORD(dwRet);
+               return (int)(short)LOWORD(dwRet);
+       }
+
+#ifndef _ATL_NO_COM
+       BOOL GetTextBSTR(int nPane, BSTR& bstrText, int* pType = NULL) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               ATLASSERT(bstrText == NULL);
+               int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L));
+               if(nLength == 0)
+                       return FALSE;
+
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpstrText = buff.Allocate(nLength + 1);
+               if(lpstrText == NULL)
+                       return FALSE;
+
+               if(!GetText(nPane, lpstrText, pType))
+                       return FALSE;
+
+               bstrText = ::SysAllocString(T2OLE(lpstrText));
+               return (bstrText != NULL) ? TRUE : FALSE;
+       }
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       int GetText(int nPane, _CSTRING_NS::CString& strText, int* pType = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L));
+               if(nLength == 0)
+                       return 0;
+
+               LPTSTR lpstr = strText.GetBufferSetLength(nLength);
+               if(lpstr == NULL)
+                       return 0;
+               return GetText(nPane, lpstr, pType);
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       BOOL SetText(int nPane, LPCTSTR lpszText, int nType = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               return (BOOL)::SendMessage(m_hWnd, SB_SETTEXT, (nPane | nType), (LPARAM)lpszText);
+       }
+
+       BOOL GetRect(int nPane, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               return (BOOL)::SendMessage(m_hWnd, SB_GETRECT, nPane, (LPARAM)lpRect);
+       }
+
+       BOOL GetBorders(int* pBorders) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, SB_GETBORDERS, 0, (LPARAM)pBorders);
+       }
+
+       BOOL GetBorders(int& nHorz, int& nVert, int& nSpacing) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int borders[3] = { 0, 0, 0 };
+               BOOL bResult = (BOOL)::SendMessage(m_hWnd, SB_GETBORDERS, 0, (LPARAM)&borders);
+               if(bResult)
+               {
+                       nHorz = borders[0];
+                       nVert = borders[1];
+                       nSpacing = borders[2];
+               }
+               return bResult;
+       }
+
+       void SetMinHeight(int nMin)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, SB_SETMINHEIGHT, nMin, 0L);
+       }
+
+       BOOL SetSimple(BOOL bSimple = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, SB_SIMPLE, bSimple, 0L);
+       }
+
+       BOOL IsSimple() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, SB_ISSIMPLE, 0, 0L);
+       }
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, SB_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, SB_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+
+       void GetTipText(int nPane, LPTSTR lpstrText, int nSize) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               ::SendMessage(m_hWnd, SB_GETTIPTEXT, MAKEWPARAM(nPane, nSize), (LPARAM)lpstrText);
+       }
+
+       void SetTipText(int nPane, LPCTSTR lpstrText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               ::SendMessage(m_hWnd, SB_SETTIPTEXT, nPane, (LPARAM)lpstrText);
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+#if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500))
+       COLORREF SetBkColor(COLORREF clrBk)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, SB_SETBKCOLOR, 0, (LPARAM)clrBk);
+       }
+
+       HICON GetIcon(int nPane) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               return (HICON)::SendMessage(m_hWnd, SB_GETICON, nPane, 0L);
+       }
+
+       BOOL SetIcon(int nPane, HICON hIcon)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPane < 256);
+               return (BOOL)::SendMessage(m_hWnd, SB_SETICON, nPane, (LPARAM)hIcon);
+       }
+#endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500))
+};
+
+typedef CStatusBarCtrlT<ATL::CWindow>   CStatusBarCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTabCtrl
+
+template <class TBase>
+class CTabCtrlT : public TBase
+{
+public:
+// Constructors
+       CTabCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CTabCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_TABCONTROL;
+       }
+
+       CImageList GetImageList() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TCM_GETIMAGELIST, 0, 0L));
+       }
+
+       CImageList SetImageList(HIMAGELIST hImageList)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TCM_SETIMAGELIST, 0, (LPARAM)hImageList));
+       }
+
+       int GetItemCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TCM_GETITEMCOUNT, 0, 0L);
+       }
+
+       BOOL GetItem(int nItem, LPTCITEM pTabCtrlItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TCM_GETITEM, nItem, (LPARAM)pTabCtrlItem);
+       }
+
+       BOOL SetItem(int nItem, LPTCITEM pTabCtrlItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TCM_SETITEM, nItem, (LPARAM)pTabCtrlItem);
+       }
+
+       int SetItem(int nItem, UINT mask, LPCTSTR lpszItem, DWORD dwState, DWORD dwStateMask, int iImage, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TCITEM tci = { 0 };
+               tci.mask = mask;
+               tci.pszText = (LPTSTR) lpszItem;
+               tci.dwState = dwState;
+               tci.dwStateMask = dwStateMask;
+               tci.iImage = iImage;
+               tci.lParam = lParam;
+               return (int)::SendMessage(m_hWnd, TCM_SETITEM, nItem, (LPARAM)&tci);
+       }
+
+       BOOL GetItemRect(int nItem, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TCM_GETITEMRECT, nItem, (LPARAM)lpRect);
+       }
+
+       int GetCurSel() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TCM_GETCURSEL, 0, 0L);
+       }
+
+       int SetCurSel(int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TCM_SETCURSEL, nItem, 0L);
+       }
+
+       SIZE SetItemSize(SIZE size)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwSize = (DWORD)::SendMessage(m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(size.cx, size.cy));
+               SIZE sizeRet = { GET_X_LPARAM(dwSize), GET_Y_LPARAM(dwSize) };
+               return sizeRet;
+       }
+
+       void SetItemSize(int cx, int cy)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(cx, cy));
+       }
+
+       void SetPadding(SIZE size)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TCM_SETPADDING, 0, MAKELPARAM(size.cx, size.cy));
+       }
+
+       int GetRowCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TCM_GETROWCOUNT, 0, 0L);
+       }
+
+#ifndef _WIN32_WCE
+       CToolTipCtrl GetTooltips() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TCM_GETTOOLTIPS, 0, 0L));
+       }
+
+       void SetTooltips(HWND hWndToolTip)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TCM_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       int GetCurFocus() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TCM_GETCURFOCUS, 0, 0L);
+       }
+
+       void SetCurFocus(int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TCM_SETCURFOCUS, nItem, 0L);
+       }
+
+       BOOL SetItemExtra(int cbExtra)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetItemCount() == 0);   // must be empty
+               return (BOOL)::SendMessage(m_hWnd, TCM_SETITEMEXTRA, cbExtra, 0L);
+       }
+
+       int SetMinTabWidth(int nWidth = -1)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TCM_SETMINTABWIDTH, 0, nWidth);
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       DWORD GetExtendedStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TCM_GETEXTENDEDSTYLE, 0, 0L);
+       }
+
+       DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, TCM_SETEXTENDEDSTYLE, dwExMask, dwExStyle);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TCM_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TCM_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // !_WIN32_WCE
+#endif // (_WIN32_IE >= 0x0400)
+
+// Operations
+       int InsertItem(int nItem, LPTCITEM pTabCtrlItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)pTabCtrlItem);
+       }
+
+       int InsertItem(int nItem, UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TCITEM tci = { 0 };
+               tci.mask = mask;
+               tci.pszText = (LPTSTR) lpszItem;
+               tci.iImage = iImage;
+               tci.lParam = lParam;
+               return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci);
+       }
+
+       int InsertItem(int nItem, LPCTSTR lpszItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TCITEM tci = { 0 };
+               tci.mask = TCIF_TEXT;
+               tci.pszText = (LPTSTR) lpszItem;
+               return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci);
+       }
+
+       int AddItem(LPTCITEM pTabCtrlItem)
+       {
+               return InsertItem(GetItemCount(), pTabCtrlItem);
+       }
+
+       int AddItem(UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam)
+       {
+               return InsertItem(GetItemCount(), mask, lpszItem, iImage, lParam);
+       }
+
+       int AddItem(LPCTSTR lpszItem)
+       {
+               return InsertItem(GetItemCount(), lpszItem);
+       }
+
+       BOOL DeleteItem(int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TCM_DELETEITEM, nItem, 0L);
+       }
+
+       BOOL DeleteAllItems()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TCM_DELETEALLITEMS, 0, 0L);
+       }
+
+       void AdjustRect(BOOL bLarger, LPRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TCM_ADJUSTRECT, bLarger, (LPARAM)lpRect);
+       }
+
+       void RemoveImage(int nImage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TCM_REMOVEIMAGE, nImage, 0L);
+       }
+
+       int HitTest(TC_HITTESTINFO* pHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TCM_HITTEST, 0, (LPARAM)pHitTestInfo);
+       }
+
+       void DeselectAll(BOOL bExcludeFocus = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TCM_DESELECTALL, bExcludeFocus, 0L);
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       BOOL HighlightItem(int nIndex, BOOL bHighlight = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TCM_HIGHLIGHTITEM, nIndex, MAKELPARAM(bHighlight, 0));
+       }
+#endif // (_WIN32_IE >= 0x0400)
+};
+
+typedef CTabCtrlT<ATL::CWindow>   CTabCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTrackBarCtrl
+
+template <class TBase>
+class CTrackBarCtrlT : public TBase
+{
+public:
+// Constructors
+       CTrackBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CTrackBarCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return TRACKBAR_CLASS;
+       }
+
+       int GetLineSize() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETLINESIZE, 0, 0L);
+       }
+
+       int SetLineSize(int nSize)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_SETLINESIZE, 0, nSize);
+       }
+
+       int GetPageSize() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETPAGESIZE, 0, 0L);
+       }
+
+       int SetPageSize(int nSize)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_SETPAGESIZE, 0, nSize);
+       }
+
+       int GetRangeMin() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETRANGEMIN, 0, 0L);
+       }
+
+       void SetRangeMin(int nMin, BOOL bRedraw = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETRANGEMIN, bRedraw, nMin);
+       }
+
+       int GetRangeMax() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETRANGEMAX, 0, 0L);
+       }
+
+       void SetRangeMax(int nMax, BOOL bRedraw = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETRANGEMAX, bRedraw, nMax);
+       }
+
+       void GetRange(int& nMin, int& nMax) const
+       {
+               nMin = GetRangeMin();
+               nMax = GetRangeMax();
+       }
+
+       void SetRange(int nMin, int nMax, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETRANGE, bRedraw, MAKELPARAM(nMin, nMax));
+       }
+
+       int GetSelStart() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETSELSTART, 0, 0L);
+       }
+
+       void SetSelStart(int nMin)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETSELSTART, 0, (LPARAM)nMin);
+       }
+
+       int GetSelEnd() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETSELEND, 0, 0L);
+       }
+
+       void SetSelEnd(int nMax)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETSELEND, 0, (LPARAM)nMax);
+       }
+
+       void GetSelection(int& nMin, int& nMax) const
+       {
+               nMin = GetSelStart();
+               nMax = GetSelEnd();
+       }
+
+       void SetSelection(int nMin, int nMax)
+       {
+               SetSelStart(nMin);
+               SetSelEnd(nMax);
+       }
+
+       void GetChannelRect(LPRECT lprc) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_GETCHANNELRECT, 0, (LPARAM)lprc);
+       }
+
+       void GetThumbRect(LPRECT lprc) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_GETTHUMBRECT, 0, (LPARAM)lprc);
+       }
+
+       int GetPos() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETPOS, 0, 0L);
+       }
+
+       void SetPos(int nPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETPOS, TRUE, nPos);
+       }
+
+       UINT GetNumTics() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, TBM_GETNUMTICS, 0, 0L);
+       }
+
+       DWORD* GetTicArray() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD*)::SendMessage(m_hWnd, TBM_GETPTICS, 0, 0L);
+       }
+
+       int GetTic(int nTic) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETTIC, nTic, 0L);
+       }
+
+       BOOL SetTic(int nTic)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TBM_SETTIC, 0, nTic);
+       }
+
+       int GetTicPos(int nTic) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETTICPOS, nTic, 0L);
+       }
+
+       void SetTicFreq(int nFreq)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETTICFREQ, nFreq, 0L);
+       }
+
+       int GetThumbLength() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_GETTHUMBLENGTH, 0, 0L);
+       }
+
+       void SetThumbLength(int nLength)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETTHUMBLENGTH, nLength, 0L);
+       }
+
+       void SetSel(int nStart, int nEnd, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & TBS_ENABLESELRANGE) != 0);
+               ::SendMessage(m_hWnd, TBM_SETSEL, bRedraw, MAKELPARAM(nStart, nEnd));
+       }
+
+       ATL::CWindow GetBuddy(BOOL bLeft = TRUE) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ATL::CWindow((HWND)::SendMessage(m_hWnd, TBM_GETBUDDY, bLeft, 0L));
+       }
+
+       ATL::CWindow SetBuddy(HWND hWndBuddy, BOOL bLeft = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ATL::CWindow((HWND)::SendMessage(m_hWnd, TBM_SETBUDDY, bLeft, (LPARAM)hWndBuddy));
+       }
+
+#ifndef _WIN32_WCE
+       CToolTipCtrl GetToolTips() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TBM_GETTOOLTIPS, 0, 0L));
+       }
+
+       void SetToolTips(HWND hWndTT)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETTOOLTIPS, (WPARAM)hWndTT, 0L);
+       }
+
+       int SetTipSide(int nSide)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, TBM_SETTIPSIDE, nSide, 0L);
+       }
+#endif // !_WIN32_WCE
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TBM_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, TBM_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+// Operations
+       void ClearSel(BOOL bRedraw = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_CLEARSEL, bRedraw, 0L);
+       }
+
+       void VerifyPos()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_SETPOS, FALSE, 0L);
+       }
+
+       void ClearTics(BOOL bRedraw = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, TBM_CLEARTICS, bRedraw, 0L);
+       }
+};
+
+typedef CTrackBarCtrlT<ATL::CWindow>   CTrackBarCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CUpDownCtrl
+
+template <class TBase>
+class CUpDownCtrlT : public TBase
+{
+public:
+// Constructors
+       CUpDownCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CUpDownCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return UPDOWN_CLASS;
+       }
+
+       UINT GetAccel(int nAccel, UDACCEL* pAccel) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)LOWORD(::SendMessage(m_hWnd, UDM_GETACCEL, nAccel, (LPARAM)pAccel));
+       }
+
+       BOOL SetAccel(int nAccel, UDACCEL* pAccel)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)LOWORD(::SendMessage(m_hWnd, UDM_SETACCEL, nAccel, (LPARAM)pAccel));
+       }
+
+       UINT GetBase() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)LOWORD(::SendMessage(m_hWnd, UDM_GETBASE, 0, 0L));
+       }
+
+       int SetBase(int nBase)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, UDM_SETBASE, nBase, 0L);
+       }
+
+       ATL::CWindow GetBuddy() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ATL::CWindow((HWND)::SendMessage(m_hWnd, UDM_GETBUDDY, 0, 0L));
+       }
+
+       ATL::CWindow SetBuddy(HWND hWndBuddy)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ATL::CWindow((HWND)::SendMessage(m_hWnd, UDM_SETBUDDY, (WPARAM)hWndBuddy, 0L));
+       }
+
+       int GetPos(LPBOOL lpbError = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, UDM_GETPOS, 0, 0L);
+               // Note: Seems that Windows always sets error to TRUE if
+               // UDS_SETBUDDYINT style is not used
+               if(lpbError != NULL)
+                       *lpbError = (HIWORD(dwRet) != 0) ? TRUE : FALSE;
+               return (int)(short)LOWORD(dwRet);
+       }
+
+       int SetPos(int nPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)(short)LOWORD(::SendMessage(m_hWnd, UDM_SETPOS, 0, MAKELPARAM(nPos, 0)));
+       }
+
+       DWORD GetRange() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, UDM_GETRANGE, 0, 0L);
+       }
+
+       void GetRange(int& nLower, int& nUpper) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, UDM_GETRANGE, 0, 0L);
+               nLower = (int)(short)HIWORD(dwRet);
+               nUpper = (int)(short)LOWORD(dwRet);
+       }
+
+       void SetRange(int nLower, int nUpper)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, UDM_SETRANGE, 0, MAKELPARAM(nUpper, nLower));
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       void SetRange32(int nLower, int nUpper)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, UDM_SETRANGE32, nLower, nUpper);
+       }
+
+       void GetRange32(int& nLower, int& nUpper) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, UDM_GETRANGE32, (WPARAM)&nLower, (LPARAM)&nUpper);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, UDM_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, UDM_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // !_WIN32_WCE
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       int GetPos32(LPBOOL lpbError = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               // Note: Seems that Windows always sets error to TRUE if
+               // UDS_SETBUDDYINT style is not used
+               return (int)::SendMessage(m_hWnd, UDM_GETPOS32, 0, (LPARAM)lpbError);
+       }
+
+       int SetPos32(int nPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, UDM_SETPOS32, 0, (LPARAM)nPos);
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+};
+
+typedef CUpDownCtrlT<ATL::CWindow>   CUpDownCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CProgressBarCtrl
+
+template <class TBase>
+class CProgressBarCtrlT : public TBase
+{
+public:
+// Constructors
+       CProgressBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CProgressBarCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return PROGRESS_CLASS;
+       }
+
+       DWORD SetRange(int nLower, int nUpper)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, PBM_SETRANGE, 0, MAKELPARAM(nLower, nUpper));
+       }
+
+       int SetPos(int nPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_SETPOS, nPos, 0L));
+       }
+
+       int OffsetPos(int nPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_DELTAPOS, nPos, 0L));
+       }
+
+       int SetStep(int nStep)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_SETSTEP, nStep, 0L));
+       }
+
+       UINT GetPos() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, PBM_GETPOS, 0, 0L);
+       }
+
+       void GetRange(PPBRANGE pPBRange) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pPBRange != NULL);
+               ::SendMessage(m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)pPBRange);
+       }
+
+       void GetRange(int& nLower, int& nUpper) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               PBRANGE range = { 0 };
+               ::SendMessage(m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)&range);
+               nLower = range.iLow;
+               nUpper = range.iHigh;
+       }
+
+       int GetRangeLimit(BOOL bLowLimit) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PBM_GETRANGE, bLowLimit, (LPARAM)NULL);
+       }
+
+       DWORD SetRange32(int nMin, int nMax)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, PBM_SETRANGE32, nMin, nMax);
+       }
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       COLORREF SetBarColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, PBM_SETBARCOLOR, 0, (LPARAM)clr);
+       }
+
+       COLORREF SetBkColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, PBM_SETBKCOLOR, 0, (LPARAM)clr);
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+#if (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE)
+       BOOL SetMarquee(BOOL bMarquee, UINT uUpdateTime = 0U)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, PBM_SETMARQUEE, (WPARAM)bMarquee, (LPARAM)uUpdateTime);
+       }
+#endif // (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE)
+
+#if (_WIN32_WINNT >= 0x0600)
+       int GetStep() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PBM_GETSTEP, 0, 0L);
+       }
+
+       COLORREF GetBkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, PBM_GETBKCOLOR, 0, 0L);
+       }
+
+       COLORREF GetBarColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, PBM_GETBARCOLOR, 0, 0L);
+       }
+
+       int GetState() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PBM_GETSTATE, 0, 0L);
+       }
+
+       int SetState(int nState)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PBM_SETSTATE, nState, 0L);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+// Operations
+       int StepIt()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_STEPIT, 0, 0L));
+       }
+};
+
+typedef CProgressBarCtrlT<ATL::CWindow>   CProgressBarCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CHotKeyCtrl
+
+#ifndef _WIN32_WCE
+
+template <class TBase>
+class CHotKeyCtrlT : public TBase
+{
+public:
+// Constructors
+       CHotKeyCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CHotKeyCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return HOTKEY_CLASS;
+       }
+
+       DWORD GetHotKey() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, HKM_GETHOTKEY, 0, 0L);
+       }
+
+       void GetHotKey(WORD &wVirtualKeyCode, WORD &wModifiers) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dw = (DWORD)::SendMessage(m_hWnd, HKM_GETHOTKEY, 0, 0L);
+               wVirtualKeyCode = LOBYTE(LOWORD(dw));
+               wModifiers = HIBYTE(LOWORD(dw));
+       }
+
+       void SetHotKey(WORD wVirtualKeyCode, WORD wModifiers)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, HKM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0L);
+       }
+
+       void SetRules(WORD wInvalidComb, WORD wModifiers)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, HKM_SETRULES, wInvalidComb, MAKELPARAM(wModifiers, 0));
+       }
+};
+
+typedef CHotKeyCtrlT<ATL::CWindow>   CHotKeyCtrl;
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAnimateCtrl
+
+#ifndef _WIN32_WCE
+
+template <class TBase>
+class CAnimateCtrlT : public TBase
+{
+public:
+// Constructors
+       CAnimateCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CAnimateCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return ANIMATE_CLASS;
+       }
+
+// Operations
+       BOOL Open(ATL::_U_STRINGorID FileName)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, ACM_OPEN, 0, (LPARAM)FileName.m_lpstr);
+       }
+
+       BOOL Play(UINT nFrom, UINT nTo, UINT nRep)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, ACM_PLAY, nRep, MAKELPARAM(nFrom, nTo));
+       }
+
+       BOOL Stop()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, ACM_STOP, 0, 0L);
+       }
+
+       BOOL Close()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, ACM_OPEN, 0, 0L);
+       }
+
+       BOOL Seek(UINT nTo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, ACM_PLAY, 0, MAKELPARAM(nTo, nTo));
+       }
+
+       // Vista only
+       BOOL IsPlaying() const
+       {
+#ifndef ACM_ISPLAYING
+               const UINT ACM_ISPLAYING = (WM_USER+104);
+#endif
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, ACM_ISPLAYING, 0, 0L);
+       }
+};
+
+typedef CAnimateCtrlT<ATL::CWindow>   CAnimateCtrl;
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CRichEditCtrl
+
+#ifndef _WIN32_WCE
+
+#ifdef _UNICODE
+#if (_RICHEDIT_VER == 0x0100)
+#undef RICHEDIT_CLASS
+#define RICHEDIT_CLASS L"RICHEDIT"
+#endif // (_RICHEDIT_VER == 0x0100)
+#endif // _UNICODE
+
+template <class TBase>
+class CRichEditCtrlT : public TBase
+{
+public:
+// Constructors
+       CRichEditCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CRichEditCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return RICHEDIT_CLASS;
+       }
+
+       static LPCTSTR GetLibraryName()
+       {
+#if (_RICHEDIT_VER >= 0x0200)
+               return _T("RICHED20.DLL");
+#else
+               return _T("RICHED32.DLL");
+#endif
+       }
+
+       int GetLineCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L);
+       }
+
+       BOOL GetModify() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L);
+       }
+
+       void SetModify(BOOL bModified = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L);
+       }
+
+       void GetRect(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect);
+       }
+
+       DWORD GetOptions() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_GETOPTIONS, 0, 0L);
+       }
+
+       DWORD SetOptions(WORD wOperation, DWORD dwOptions)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_SETOPTIONS, wOperation, dwOptions);
+       }
+
+       // NOTE: first word in lpszBuffer must contain the size of the buffer!
+       int GetLine(int nIndex, LPTSTR lpszBuffer) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
+       }
+
+       int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               *(LPWORD)lpszBuffer = (WORD)nMaxLength;
+               return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
+       }
+
+       BOOL CanUndo() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L);
+       }
+
+       BOOL CanPaste(UINT nFormat = 0) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_CANPASTE, nFormat, 0L);
+       }
+
+       void GetSel(LONG& nStartChar, LONG& nEndChar) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               CHARRANGE cr = { 0, 0 };
+               ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
+               nStartChar = cr.cpMin;
+               nEndChar = cr.cpMax;
+       }
+
+       void GetSel(CHARRANGE &cr) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
+       }
+
+       int SetSel(LONG nStartChar, LONG nEndChar)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               CHARRANGE cr = { nStartChar, nEndChar };
+               return (int)::SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr);
+       }
+
+       int SetSel(CHARRANGE &cr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr);
+       }
+
+       int SetSelAll()
+       {
+               return SetSel(0, -1);
+       }
+
+       int SetSelNone()
+       {
+               return SetSel(-1, 0);
+       }
+
+       DWORD GetDefaultCharFormat(CHARFORMAT& cf) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT);
+               return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf);
+       }
+
+       DWORD GetSelectionCharFormat(CHARFORMAT& cf) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT);
+               return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf);
+       }
+
+       DWORD GetEventMask() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_GETEVENTMASK, 0, 0L);
+       }
+
+       LONG GetLimitText() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L);
+       }
+
+       DWORD GetParaFormat(PARAFORMAT& pf) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               pf.cbSize = sizeof(PARAFORMAT);
+               return (DWORD)::SendMessage(m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
+       }
+
+#if (_RICHEDIT_VER >= 0x0200)
+       LONG GetSelText(LPTSTR lpstrBuff) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff);
+       }
+#else // !(_RICHEDIT_VER >= 0x0200)
+       // RichEdit 1.0 EM_GETSELTEXT is ANSI only
+       LONG GetSelText(LPSTR lpstrBuff) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff);
+       }
+#endif // !(_RICHEDIT_VER >= 0x0200)
+
+#ifndef _ATL_NO_COM
+       BOOL GetSelTextBSTR(BSTR& bstrText) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(bstrText == NULL);
+
+               CHARRANGE cr = { 0, 0 };
+               ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
+
+#if (_RICHEDIT_VER >= 0x0200)
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1);
+               if(lpstrText == NULL)
+                       return FALSE;
+               if(::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0)
+                       return FALSE;
+
+               bstrText = ::SysAllocString(T2W(lpstrText));
+#else // !(_RICHEDIT_VER >= 0x0200)
+               CTempBuffer<char, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1);
+               if(lpstrText == NULL)
+                       return FALSE;
+               if(::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0)
+                       return FALSE;
+
+               bstrText = ::SysAllocString(A2W(lpstrText));
+#endif // !(_RICHEDIT_VER >= 0x0200)
+
+               return (bstrText != NULL) ? TRUE : FALSE;
+       }
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       LONG GetSelText(_CSTRING_NS::CString& strText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               CHARRANGE cr = { 0, 0 };
+               ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
+
+#if (_RICHEDIT_VER >= 0x0200)
+               LONG lLen = 0;
+               LPTSTR lpstrText = strText.GetBufferSetLength(cr.cpMax - cr.cpMin);
+               if(lpstrText != NULL)
+               {
+                       lLen = (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText);
+                       strText.ReleaseBuffer();
+               }
+#else // !(_RICHEDIT_VER >= 0x0200)
+               CTempBuffer<char, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1);
+               if(lpstrText == NULL)
+                       return 0;
+               LONG lLen = (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText);
+               if(lLen == 0)
+                       return 0;
+
+               USES_CONVERSION;
+               strText = A2T(lpstrText);
+#endif // !(_RICHEDIT_VER >= 0x0200)
+
+               return lLen;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       WORD GetSelectionType() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (WORD)::SendMessage(m_hWnd, EM_SELECTIONTYPE, 0, 0L);
+       }
+
+       COLORREF SetBackgroundColor(COLORREF cr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, EM_SETBKGNDCOLOR, 0, cr);
+       }
+
+       COLORREF SetBackgroundColor()   // sets to system background
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, EM_SETBKGNDCOLOR, 1, 0);
+       }
+
+       BOOL SetCharFormat(CHARFORMAT& cf, WORD wFlags)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf);
+       }
+
+       BOOL SetDefaultCharFormat(CHARFORMAT& cf)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf);
+       }
+
+       BOOL SetSelectionCharFormat(CHARFORMAT& cf)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+       }
+
+       BOOL SetWordCharFormat(CHARFORMAT& cf)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf);
+       }
+
+       DWORD SetEventMask(DWORD dwEventMask)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_SETEVENTMASK, 0, dwEventMask);
+       }
+
+       BOOL SetParaFormat(PARAFORMAT& pf)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               pf.cbSize = sizeof(PARAFORMAT);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
+       }
+
+       BOOL SetTargetDevice(HDC hDC, int cxLineWidth)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETTARGETDEVICE, (WPARAM)hDC, cxLineWidth);
+       }
+
+       int GetTextLength() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0L);
+       }
+
+       BOOL SetReadOnly(BOOL bReadOnly = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L);
+       }
+
+       int GetFirstVisibleLine() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L);
+       }
+
+       EDITWORDBREAKPROCEX GetWordBreakProcEx() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (EDITWORDBREAKPROCEX)::SendMessage(m_hWnd, EM_GETWORDBREAKPROCEX, 0, 0L);
+       }
+
+       EDITWORDBREAKPROCEX SetWordBreakProcEx(EDITWORDBREAKPROCEX pfnEditWordBreakProcEx)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (EDITWORDBREAKPROCEX)::SendMessage(m_hWnd, EM_SETWORDBREAKPROCEX, 0, (LPARAM)pfnEditWordBreakProcEx);
+       }
+
+       int GetTextRange(TEXTRANGE* pTextRange) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)pTextRange);
+       }
+
+#if (_RICHEDIT_VER >= 0x0200)
+       int GetTextRange(LONG nStartChar, LONG nEndChar, LPTSTR lpstrText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TEXTRANGE tr = { 0 };
+               tr.chrg.cpMin = nStartChar;
+               tr.chrg.cpMax = nEndChar;
+               tr.lpstrText = lpstrText;
+               return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
+       }
+#else // !(_RICHEDIT_VER >= 0x0200)
+
+       int GetTextRange(LONG nStartChar, LONG nEndChar, LPSTR lpstrText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               TEXTRANGE tr = { 0 };
+               tr.chrg.cpMin = nStartChar;
+               tr.chrg.cpMax = nEndChar;
+               tr.lpstrText = lpstrText;
+               return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
+       }
+#endif // !(_RICHEDIT_VER >= 0x0200)
+
+#if (_RICHEDIT_VER >= 0x0200)
+       DWORD GetDefaultCharFormat(CHARFORMAT2& cf) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT2);
+               return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf);
+       }
+
+       BOOL SetCharFormat(CHARFORMAT2& cf, WORD wFlags)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT2);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf);
+       }
+
+       BOOL SetDefaultCharFormat(CHARFORMAT2& cf)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT2);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf);
+       }
+
+       DWORD GetSelectionCharFormat(CHARFORMAT2& cf) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT2);
+               return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf);
+       }
+
+       BOOL SetSelectionCharFormat(CHARFORMAT2& cf)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT2);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+       }
+
+       BOOL SetWordCharFormat(CHARFORMAT2& cf)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               cf.cbSize = sizeof(CHARFORMAT2);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf);
+       }
+
+       DWORD GetParaFormat(PARAFORMAT2& pf) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               pf.cbSize = sizeof(PARAFORMAT2);
+               return (DWORD)::SendMessage(m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
+       }
+
+       BOOL SetParaFormat(PARAFORMAT2& pf)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               pf.cbSize = sizeof(PARAFORMAT2);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
+       }
+
+       TEXTMODE GetTextMode() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (TEXTMODE)::SendMessage(m_hWnd, EM_GETTEXTMODE, 0, 0L);
+       }
+
+       BOOL SetTextMode(TEXTMODE enumTextMode)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return !(BOOL)::SendMessage(m_hWnd, EM_SETTEXTMODE, enumTextMode, 0L);
+       }
+
+       UNDONAMEID GetUndoName() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UNDONAMEID)::SendMessage(m_hWnd, EM_GETUNDONAME, 0, 0L);
+       }
+
+       UNDONAMEID GetRedoName() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UNDONAMEID)::SendMessage(m_hWnd, EM_GETREDONAME, 0, 0L);
+       }
+
+       BOOL CanRedo() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0L);
+       }
+
+       BOOL GetAutoURLDetect() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_GETAUTOURLDETECT, 0, 0L);
+       }
+
+       BOOL SetAutoURLDetect(BOOL bAutoDetect = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return !(BOOL)::SendMessage(m_hWnd, EM_AUTOURLDETECT, bAutoDetect, 0L);
+       }
+
+       // this method is deprecated, please use SetAutoURLDetect
+       BOOL EnableAutoURLDetect(BOOL bEnable = TRUE) { return SetAutoURLDetect(bEnable); }
+
+       UINT SetUndoLimit(UINT uUndoLimit)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_SETUNDOLIMIT, uUndoLimit, 0L);
+       }
+
+       void SetPalette(HPALETTE hPalette)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETPALETTE, (WPARAM)hPalette, 0L);
+       }
+
+       int GetTextEx(GETTEXTEX* pGetTextEx, LPTSTR lpstrText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)pGetTextEx, (LPARAM)lpstrText);
+       }
+
+       int GetTextEx(LPTSTR lpstrText, int nTextLen, DWORD dwFlags = GT_DEFAULT, UINT uCodePage = CP_ACP, LPCSTR lpDefaultChar = NULL, LPBOOL lpUsedDefChar = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               GETTEXTEX gte = { 0 };
+               gte.cb = nTextLen * sizeof(TCHAR);
+               gte.codepage = uCodePage;
+               gte.flags = dwFlags;
+               gte.lpDefaultChar = lpDefaultChar;
+               gte.lpUsedDefChar = lpUsedDefChar;
+               return (int)::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)&gte, (LPARAM)lpstrText);
+       }
+
+       int GetTextLengthEx(GETTEXTLENGTHEX* pGetTextLengthEx) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)pGetTextLengthEx, 0L);
+       }
+
+       int GetTextLengthEx(DWORD dwFlags = GTL_DEFAULT, UINT uCodePage = CP_ACP) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               GETTEXTLENGTHEX gtle = { 0 };
+               gtle.codepage = uCodePage;
+               gtle.flags = dwFlags;
+               return (int)::SendMessage(m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtle, 0L);
+       }
+#endif // (_RICHEDIT_VER >= 0x0200)
+
+#if (_RICHEDIT_VER >= 0x0300)
+       int SetTextEx(SETTEXTEX* pSetTextEx, LPCTSTR lpstrText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_SETTEXTEX, (WPARAM)pSetTextEx, (LPARAM)lpstrText);
+       }
+
+       int SetTextEx(LPCTSTR lpstrText, DWORD dwFlags = ST_DEFAULT, UINT uCodePage = CP_ACP)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               SETTEXTEX ste = { 0 };
+               ste.flags = dwFlags;
+               ste.codepage = uCodePage;
+               return (int)::SendMessage(m_hWnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpstrText);
+       }
+
+       int GetEditStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_GETEDITSTYLE, 0, 0L);
+       }
+
+       int SetEditStyle(int nStyle, int nMask = -1)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               if(nMask == -1)
+                       nMask = nStyle;   // set everything specified
+               return (int)::SendMessage(m_hWnd, EM_SETEDITSTYLE, nStyle, nMask);
+       }
+
+       BOOL SetFontSize(int nFontSizeDelta)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nFontSizeDelta >= -1637 && nFontSizeDelta <= 1638);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETFONTSIZE, nFontSizeDelta, 0L);
+       }
+
+       void GetScrollPos(LPPOINT lpPoint) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpPoint != NULL);
+               ::SendMessage(m_hWnd, EM_GETSCROLLPOS, 0, (LPARAM)lpPoint);
+       }
+
+       void SetScrollPos(LPPOINT lpPoint)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpPoint != NULL);
+               ::SendMessage(m_hWnd, EM_SETSCROLLPOS, 0, (LPARAM)lpPoint);
+       }
+
+       BOOL GetZoom(int& nNum, int& nDen) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_GETZOOM, (WPARAM)&nNum, (LPARAM)&nDen);
+       }
+
+       BOOL SetZoom(int nNum, int nDen)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nNum >= 0 && nNum <= 64);
+               ATLASSERT(nDen >= 0 && nDen <= 64);
+               return (BOOL)::SendMessage(m_hWnd, EM_SETZOOM, nNum, nDen);
+       }
+
+       BOOL SetZoomOff()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETZOOM, 0, 0L);
+       }
+#endif // (_RICHEDIT_VER >= 0x0300)
+
+// Operations
+       void LimitText(LONG nChars = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_EXLIMITTEXT, 0, nChars);
+       }
+
+       int LineFromChar(LONG nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_EXLINEFROMCHAR, 0, nIndex);
+       }
+
+       POINT PosFromChar(LONG nChar) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               POINT point = { 0, 0 };
+               ::SendMessage(m_hWnd, EM_POSFROMCHAR, (WPARAM)&point, nChar);
+               return point;
+       }
+
+       int CharFromPos(POINT pt) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               POINTL ptl = { pt.x, pt.y };
+               return (int)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, (LPARAM)&ptl);
+       }
+
+       void EmptyUndoBuffer()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L);
+       }
+
+       int LineIndex(int nLine = -1) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L);
+       }
+
+       int LineLength(int nLine = -1) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L);
+       }
+
+       BOOL LineScroll(int nLines, int nChars = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_LINESCROLL, nChars, nLines);
+       }
+
+       void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
+       }
+
+       void SetRect(LPCRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect);
+       }
+
+       BOOL DisplayBand(LPRECT pDisplayRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_DISPLAYBAND, 0, (LPARAM)pDisplayRect);
+       }
+
+       LONG FindText(DWORD dwFlags, FINDTEXT& ft) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+#if (_RICHEDIT_VER >= 0x0200) && defined(_UNICODE)
+               return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTW, dwFlags, (LPARAM)&ft);
+#else
+               return (LONG)::SendMessage(m_hWnd, EM_FINDTEXT, dwFlags, (LPARAM)&ft);
+#endif
+       }
+
+       LONG FindText(DWORD dwFlags, FINDTEXTEX& ft) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+#if (_RICHEDIT_VER >= 0x0200) && defined(_UNICODE)
+               return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTEXW, dwFlags, (LPARAM)&ft);
+#else
+               return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTEX, dwFlags, (LPARAM)&ft);
+#endif
+       }
+
+       LONG FormatRange(FORMATRANGE& fr, BOOL bDisplay = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)&fr);
+       }
+
+       LONG FormatRange(FORMATRANGE* pFormatRange, BOOL bDisplay = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)pFormatRange);
+       }
+
+       void HideSelection(BOOL bHide = TRUE, BOOL bChangeStyle = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_HIDESELECTION, bHide, bChangeStyle);
+       }
+
+       void PasteSpecial(UINT uClipFormat, DWORD dwAspect = 0, HMETAFILE hMF = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               REPASTESPECIAL reps = { dwAspect, (DWORD_PTR)hMF };
+               ::SendMessage(m_hWnd, EM_PASTESPECIAL, uClipFormat, (LPARAM)&reps);
+       }
+
+       void RequestResize()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_REQUESTRESIZE, 0, 0L);
+       }
+
+       LONG StreamIn(UINT uFormat, EDITSTREAM& es)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_STREAMIN, uFormat, (LPARAM)&es);
+       }
+
+       LONG StreamOut(UINT uFormat, EDITSTREAM& es)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_STREAMOUT, uFormat, (LPARAM)&es);
+       }
+
+       DWORD FindWordBreak(int nCode, LONG nStartChar)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_FINDWORDBREAK, nCode, nStartChar);
+       }
+
+       // Additional operations
+       void ScrollCaret()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
+       }
+
+       int InsertText(long nInsertAfterChar, LPCTSTR lpstrText, BOOL bCanUndo = FALSE)
+       {
+               int nRet = SetSel(nInsertAfterChar, nInsertAfterChar);
+               ReplaceSel(lpstrText, bCanUndo);
+               return nRet;
+       }
+
+       int AppendText(LPCTSTR lpstrText, BOOL bCanUndo = FALSE)
+       {
+               return InsertText(GetWindowTextLength(), lpstrText, bCanUndo);
+       }
+
+       // Clipboard operations
+       BOOL Undo()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L);
+       }
+
+       void Clear()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
+       }
+
+       void Copy()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_COPY, 0, 0L);
+       }
+
+       void Cut()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_CUT, 0, 0L);
+       }
+
+       void Paste()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
+       }
+
+       // OLE support
+       IRichEditOle* GetOleInterface() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               IRichEditOle *pRichEditOle = NULL;
+               ::SendMessage(m_hWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
+               return pRichEditOle;
+       }
+
+       BOOL SetOleCallback(IRichEditOleCallback* pCallback)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETOLECALLBACK, 0, (LPARAM)pCallback);
+       }
+
+#if (_RICHEDIT_VER >= 0x0200)
+       BOOL Redo()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_REDO, 0, 0L);
+       }
+
+       void StopGroupTyping()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_STOPGROUPTYPING, 0, 0L);
+       }
+
+       void ShowScrollBar(int nBarType, BOOL bVisible = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SHOWSCROLLBAR, nBarType, bVisible);
+       }
+#endif // (_RICHEDIT_VER >= 0x0200)
+
+#if (_RICHEDIT_VER >= 0x0300)
+       BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
+       }
+
+       BOOL SetTabStops()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L);
+       }
+
+       BOOL SetTabStops(const int& cxEachStop)    // takes an 'int'
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
+       }
+#endif // (_RICHEDIT_VER >= 0x0300)
+};
+
+typedef CRichEditCtrlT<ATL::CWindow>   CRichEditCtrl;
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CRichEditCommands - message handlers for standard EDIT commands
+
+#ifndef _WIN32_WCE
+
+// Chain to CRichEditCommands message map. Your class must also derive from CRichEditCtrl.
+// Example:
+// class CMyRichEdit : public CWindowImpl<CMyRichEdit, CRichEditCtrl>,
+//                     public CRichEditCommands<CMyRichEdit>
+// {
+// public:
+//      BEGIN_MSG_MAP(CMyRichEdit)
+//              // your handlers...
+//              CHAIN_MSG_MAP_ALT(CRichEditCommands<CMyRichEdit>, 1)
+//      END_MSG_MAP()
+//      // other stuff...
+// };
+
+template <class T>
+class CRichEditCommands : public CEditCommands< T >
+{
+public:
+       BEGIN_MSG_MAP(CRichEditCommands< T >)
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_EDIT_CLEAR, CEditCommands< T >::OnEditClear)
+               COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, CEditCommands< T >::OnEditClearAll)
+               COMMAND_ID_HANDLER(ID_EDIT_COPY, CEditCommands< T >::OnEditCopy)
+               COMMAND_ID_HANDLER(ID_EDIT_CUT, CEditCommands< T >::OnEditCut)
+               COMMAND_ID_HANDLER(ID_EDIT_PASTE, CEditCommands< T >::OnEditPaste)
+               COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, CEditCommands< T >::OnEditSelectAll)
+               COMMAND_ID_HANDLER(ID_EDIT_UNDO, CEditCommands< T >::OnEditUndo)
+#if (_RICHEDIT_VER >= 0x0200)
+               COMMAND_ID_HANDLER(ID_EDIT_REDO, OnEditRedo)
+#endif // (_RICHEDIT_VER >= 0x0200)
+       END_MSG_MAP()
+
+#if (_RICHEDIT_VER >= 0x0200)
+       LRESULT OnEditRedo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Redo();
+               return 0;
+       }
+#endif // (_RICHEDIT_VER >= 0x0200)
+
+// State (update UI) helpers
+       BOOL CanCut() const
+       { return HasSelection(); }
+
+       BOOL CanCopy() const
+       { return HasSelection(); }
+
+       BOOL CanClear() const
+       { return HasSelection(); }
+
+// Implementation
+       BOOL HasSelection() const
+       {
+               const T* pT = static_cast<const T*>(this);
+               return (pT->GetSelectionType() != SEL_EMPTY);
+       }
+};
+
+#endif // _WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDragListBox
+
+#ifndef _WIN32_WCE
+
+template <class TBase>
+class CDragListBoxT : public CListBoxT< TBase >
+{
+public:
+// Constructors
+       CDragListBoxT(HWND hWnd = NULL) : CListBoxT< TBase >(hWnd)
+       { }
+
+       CDragListBoxT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+               if(hWnd != NULL)
+                       MakeDragList();
+               return hWnd;
+       }
+
+// Operations
+       BOOL MakeDragList()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
+               return ::MakeDragList(m_hWnd);
+       }
+
+       int LBItemFromPt(POINT pt, BOOL bAutoScroll = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::LBItemFromPt(m_hWnd, pt, bAutoScroll);
+       }
+
+       void DrawInsert(int nItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::DrawInsert(GetParent(), m_hWnd, nItem);
+       }
+
+       static UINT GetDragListMessage()
+       {
+               static UINT uDragListMessage = 0;
+               if(uDragListMessage == 0)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDragListBox::GetDragListMessage.\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(uDragListMessage == 0)
+                               uDragListMessage = ::RegisterWindowMessage(DRAGLISTMSGSTRING);
+
+                       lock.Unlock();
+               }
+               ATLASSERT(uDragListMessage != 0);
+               return uDragListMessage;
+       }
+};
+
+typedef CDragListBoxT<ATL::CWindow>   CDragListBox;
+
+template <class T>
+class CDragListNotifyImpl
+{
+public:
+       BEGIN_MSG_MAP(CDragListNotifyImpl< T >)
+               MESSAGE_HANDLER(CDragListBox::GetDragListMessage(), OnDragListNotify)
+       END_MSG_MAP()
+
+       LRESULT OnDragListNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               uMsg;   // avoid level 4 warning
+               ATLASSERT(uMsg == CDragListBox::GetDragListMessage());
+               T* pT = static_cast<T*>(this);
+               LPDRAGLISTINFO lpDragListInfo = (LPDRAGLISTINFO)lParam;
+               LRESULT lRet = 0;
+               switch(lpDragListInfo->uNotification)
+               {
+               case DL_BEGINDRAG:
+                       lRet = (LPARAM)pT->OnBeginDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
+                       break;
+               case DL_CANCELDRAG:
+                       pT->OnCancelDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
+                       break;
+               case DL_DRAGGING:
+                       lRet = (LPARAM)pT->OnDragging((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
+                       break;
+               case DL_DROPPED:
+                       pT->OnDropped((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
+                       break;
+               default:
+                       ATLTRACE2(atlTraceUI, 0, _T("Unknown DragListBox notification\n"));
+                       bHandled = FALSE;   // don't handle it
+                       break;
+               }
+               return lRet;
+       }
+
+// Overrideables
+       BOOL OnBeginDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
+       {
+               return TRUE;   // allow dragging
+       }
+
+       void OnCancelDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
+       {
+               // nothing to do
+       }
+
+       int OnDragging(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
+       {
+               return 0;   // don't change cursor
+       }
+
+       void OnDropped(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
+       {
+               // nothing to do
+       }
+};
+
+#endif // _WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CReBarCtrl
+
+template <class TBase>
+class CReBarCtrlT : public TBase
+{
+public:
+// Constructors
+       CReBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CReBarCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return REBARCLASSNAME;
+       }
+
+       UINT GetBandCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, RB_GETBANDCOUNT, 0, 0L);
+       }
+
+       BOOL GetBandInfo(int nBand, LPREBARBANDINFO lprbbi) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_GETBANDINFO, nBand, (LPARAM)lprbbi);
+       }
+
+       BOOL SetBandInfo(int nBand, LPREBARBANDINFO lprbbi)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_SETBANDINFO, nBand, (LPARAM)lprbbi);
+       }
+
+       BOOL GetBarInfo(LPREBARINFO lprbi) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_GETBARINFO, 0, (LPARAM)lprbi);
+       }
+
+       BOOL SetBarInfo(LPREBARINFO lprbi)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_SETBARINFO, 0, (LPARAM)lprbi);
+       }
+
+       CImageList GetImageList() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               REBARINFO rbi = { 0 };
+               rbi.cbSize = sizeof(REBARINFO);
+               rbi.fMask = RBIM_IMAGELIST;
+               if( (BOOL)::SendMessage(m_hWnd, RB_GETBARINFO, 0, (LPARAM)&rbi) == FALSE ) return CImageList();
+               return CImageList(rbi.himl);
+       }
+
+       BOOL SetImageList(HIMAGELIST hImageList)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               REBARINFO rbi = { 0 };
+               rbi.cbSize = sizeof(REBARINFO);
+               rbi.fMask = RBIM_IMAGELIST;
+               rbi.himl = hImageList;
+               return (BOOL)::SendMessage(m_hWnd, RB_SETBARINFO, 0, (LPARAM)&rbi);
+       }
+
+       UINT GetRowCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, RB_GETROWCOUNT, 0, 0L);
+       }
+
+       UINT GetRowHeight(int nBand) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, RB_GETROWHEIGHT, nBand, 0L);
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       COLORREF GetTextColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, RB_GETTEXTCOLOR, 0, 0L);
+       }
+
+       COLORREF SetTextColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, RB_SETTEXTCOLOR, 0, (LPARAM)clr);
+       }
+
+       COLORREF GetBkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, RB_GETBKCOLOR, 0, 0L);
+       }
+
+       COLORREF SetBkColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, RB_SETBKCOLOR, 0, (LPARAM)clr);
+       }
+
+       UINT GetBarHeight() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, RB_GETBARHEIGHT, 0, 0L);
+       }
+
+       BOOL GetRect(int nBand, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_GETRECT, nBand, (LPARAM)lpRect);
+       }
+
+#ifndef _WIN32_WCE
+       CToolTipCtrl GetToolTips() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CToolTipCtrl((HWND)::SendMessage(m_hWnd, RB_GETTOOLTIPS, 0, 0L));
+       }
+
+       void SetToolTips(HWND hwndToolTip)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_SETTOOLTIPS, (WPARAM)hwndToolTip, 0L);
+       }
+#endif // !_WIN32_WCE
+
+       void GetBandBorders(int nBand, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpRect != NULL);
+               ::SendMessage(m_hWnd, RB_GETBANDBORDERS, nBand, (LPARAM)lpRect);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetColorScheme(LPCOLORSCHEME lpColorScheme) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpColorScheme != NULL);
+               return (BOOL)::SendMessage(m_hWnd, RB_GETCOLORSCHEME, 0, (LPARAM)lpColorScheme);
+       }
+
+       void SetColorScheme(LPCOLORSCHEME lpColorScheme)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpColorScheme != NULL);
+               ::SendMessage(m_hWnd, RB_SETCOLORSCHEME, 0, (LPARAM)lpColorScheme);
+       }
+
+       HPALETTE GetPalette() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HPALETTE)::SendMessage(m_hWnd, RB_GETPALETTE, 0, 0L);
+       }
+
+       HPALETTE SetPalette(HPALETTE hPalette)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HPALETTE)::SendMessage(m_hWnd, RB_SETPALETTE, 0, (LPARAM)hPalette);
+       }
+
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // !_WIN32_WCE
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_WINNT >= 0x0501)
+       // requires uxtheme.h to be included to use MARGINS struct
+#ifndef _UXTHEME_H_
+       typedef struct _MARGINS*   PMARGINS;
+#endif // !_UXTHEME_H_
+       void GetBandMargins(PMARGINS pMargins) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_GETBANDMARGINS, 0, (LPARAM)pMargins);
+       }
+
+       void SetWindowTheme(LPCWSTR lpstrTheme)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+#if (_WIN32_IE >= 0x0600)
+       DWORD GetExtendedStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, RB_GETEXTENDEDSTYLE, 0, 0L);
+       }
+
+       DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, RB_SETEXTENDEDSTYLE, dwMask, dwStyle);
+       }
+#endif // (_WIN32_IE >= 0x0600)
+
+// Operations
+       BOOL InsertBand(int nBand, LPREBARBANDINFO lprbbi)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_INSERTBAND, nBand, (LPARAM)lprbbi);
+       }
+
+       BOOL AddBand(LPREBARBANDINFO lprbbi)
+       {
+               return InsertBand(-1, lprbbi);
+       }
+
+       BOOL DeleteBand(int nBand)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_DELETEBAND, nBand, 0L);
+       }
+
+       ATL::CWindow SetNotifyWnd(HWND hWnd)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ATL::CWindow((HWND)::SendMessage(m_hWnd, RB_SETPARENT, (WPARAM)hWnd, 0L));
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       void BeginDrag(int nBand, DWORD dwPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_BEGINDRAG, nBand, dwPos);
+       }
+
+       void BeginDrag(int nBand, int xPos, int yPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_BEGINDRAG, nBand, MAKELPARAM(xPos, yPos));
+       }
+
+       void EndDrag()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_ENDDRAG, 0, 0L);
+       }
+
+       void DragMove(DWORD dwPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_DRAGMOVE, 0, dwPos);
+       }
+
+       void DragMove(int xPos, int yPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_DRAGMOVE, 0, MAKELPARAM(xPos, yPos));
+       }
+
+#ifndef _WIN32_WCE
+       void GetDropTarget(IDropTarget** ppDropTarget) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_GETDROPTARGET, 0, (LPARAM)ppDropTarget);
+       }
+#endif // !_WIN32_WCE
+
+       void MaximizeBand(int nBand, BOOL bIdeal = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_MAXIMIZEBAND, nBand, bIdeal);
+       }
+
+       void MinimizeBand(int nBand)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_MINIMIZEBAND, nBand, 0L);
+       }
+
+       BOOL SizeToRect(LPRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_SIZETORECT, 0, (LPARAM)lpRect);
+       }
+
+       int IdToIndex(UINT uBandID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, RB_IDTOINDEX, uBandID, 0L);
+       }
+
+       int HitTest(LPRBHITTESTINFO lprbht) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, RB_HITTEST, 0, (LPARAM)lprbht);
+       }
+
+       BOOL ShowBand(int nBand, BOOL bShow)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_SHOWBAND, nBand, bShow);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL MoveBand(int nBand, int nNewPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nNewPos >= 0 && nNewPos <= ((int)GetBandCount() - 1));
+               return (BOOL)::SendMessage(m_hWnd, RB_MOVEBAND, nBand, nNewPos);
+       }
+#endif // !_WIN32_WCE
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       void PushChevron(int nBand, LPARAM lAppValue)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, RB_PUSHCHEVRON, nBand, lAppValue);
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+// Extra operations
+#if (_WIN32_IE >= 0x0400)
+       void LockBands(bool bLock)
+       {
+               int nBandCount = GetBandCount();
+               for(int i =0; i < nBandCount; i++)
+               {
+                       REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
+                       rbbi.fMask = RBBIM_STYLE;
+                       BOOL bRet = GetBandInfo(i, &rbbi);
+                       ATLASSERT(bRet);
+
+                       if((rbbi.fStyle & RBBS_GRIPPERALWAYS) == 0)
+                       {
+                               rbbi.fStyle |= RBBS_GRIPPERALWAYS;
+                               bRet = SetBandInfo(i, &rbbi);
+                               ATLASSERT(bRet);
+                               rbbi.fStyle &= ~RBBS_GRIPPERALWAYS;
+                       }
+
+                       if(bLock)
+                               rbbi.fStyle |= RBBS_NOGRIPPER;
+                       else
+                               rbbi.fStyle &= ~RBBS_NOGRIPPER;
+
+                       bRet = SetBandInfo(i, &rbbi);
+                       ATLASSERT(bRet);
+               }
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_WINNT >= 0x0600)
+       BOOL SetBandWidth(int nBand, int cxWidth)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, RB_SETBANDWIDTH, nBand, cxWidth);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+};
+
+typedef CReBarCtrlT<ATL::CWindow>   CReBarCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CComboBoxEx
+
+#ifndef _WIN32_WCE
+
+template <class TBase>
+class CComboBoxExT : public CComboBoxT< TBase >
+{
+public:
+// Constructors
+       CComboBoxExT(HWND hWnd = NULL) : CComboBoxT< TBase >(hWnd)
+       { }
+
+       CComboBoxExT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_COMBOBOXEX;
+       }
+
+       CImageList GetImageList() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, CBEM_GETIMAGELIST, 0, 0L));
+       }
+
+       CImageList SetImageList(HIMAGELIST hImageList)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CImageList((HIMAGELIST)::SendMessage(m_hWnd, CBEM_SETIMAGELIST, 0, (LPARAM)hImageList));
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       DWORD GetExtendedStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, CBEM_GETEXTENDEDSTYLE, 0, 0L);
+       }
+
+       DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, CBEM_SETEXTENDEDSTYLE, dwExMask, dwExStyle);
+       }
+
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CBEM_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CBEM_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_WINNT >= 0x0501)
+       void SetWindowTheme(LPCWSTR lpstrTheme)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, CBEM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+// Operations
+       int InsertItem(const COMBOBOXEXITEM* lpcCBItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)lpcCBItem);
+       }
+
+       int InsertItem(UINT nMask, int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, 
+                      int iIndent, int iOverlay, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               COMBOBOXEXITEM cbex = { 0 };
+               cbex.mask = nMask;
+               cbex.iItem = nIndex;
+               cbex.pszText = (LPTSTR) lpszItem;
+               cbex.iImage = nImage;
+               cbex.iSelectedImage = nSelImage;
+               cbex.iIndent = iIndent;
+               cbex.iOverlay = iOverlay;
+               cbex.lParam = lParam;
+               return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex);
+       }
+
+       int InsertItem(int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               COMBOBOXEXITEM cbex = { 0 };
+               cbex.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_INDENT | CBEIF_LPARAM;
+               cbex.iItem = nIndex;
+               cbex.pszText = (LPTSTR) lpszItem;
+               cbex.iImage = nImage;
+               cbex.iSelectedImage = nSelImage;
+               cbex.iIndent = iIndent;
+               cbex.lParam = lParam;
+               return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex);
+       }
+
+       int AddItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, int iOverlay, LPARAM lParam)
+       {
+               return InsertItem(nMask, -1, lpszItem, nImage, nSelImage, iIndent, iOverlay, lParam);
+       }
+
+       int AddItem(LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0)
+       {
+               return InsertItem(-1, lpszItem, nImage, nSelImage, iIndent, lParam);
+       }
+
+       int DeleteItem(int nIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, CBEM_DELETEITEM, nIndex, 0L);
+       }
+
+       BOOL GetItem(PCOMBOBOXEXITEM pCBItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)pCBItem);
+       }
+
+       BOOL SetItem(const COMBOBOXEXITEM* lpcCBItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)lpcCBItem);
+       }
+
+       int SetItem(int nIndex, UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, 
+                   int iIndent, int iOverlay, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               COMBOBOXEXITEM cbex = { 0 };
+               cbex.mask = nMask;
+               cbex.iItem = nIndex;
+               cbex.pszText = (LPTSTR) lpszItem;
+               cbex.iImage = nImage;
+               cbex.iSelectedImage = nSelImage;
+               cbex.iIndent = iIndent;
+               cbex.iOverlay = iOverlay;
+               cbex.lParam = lParam;
+               return (int)::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)&cbex);
+       }
+
+       BOOL GetItemText(int nIndex, LPTSTR lpszItem, int nLen) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpszItem != NULL);
+
+               COMBOBOXEXITEM cbex = { 0 };
+               cbex.mask = CBEIF_TEXT;
+               cbex.iItem = nIndex;
+               cbex.pszText = lpszItem;
+               cbex.cchTextMax = nLen;
+
+               return (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
+       }
+
+#ifndef _ATL_NO_COM
+       BOOL GetItemText(int nIndex, BSTR& bstrText) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(bstrText == NULL);
+
+               COMBOBOXEXITEM cbex = { 0 };
+               cbex.mask = CBEIF_TEXT;
+               cbex.iItem = nIndex;
+
+               LPTSTR lpstrText = NULL;
+               BOOL bRet = FALSE;
+               for(int nLen = 256; ; nLen *= 2)
+               {
+                       ATLTRY(lpstrText = new TCHAR[nLen]);
+                       if(lpstrText == NULL)
+                               break;
+                       lpstrText[0] = NULL;
+                       cbex.pszText = lpstrText;
+                       cbex.cchTextMax = nLen;
+                       bRet = (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
+                       if(!bRet || (lstrlen(cbex.pszText) < nLen - 1))
+                               break;
+                       delete [] lpstrText;
+                       lpstrText = NULL;
+               }
+
+               if(lpstrText != NULL)
+               {
+                       if(bRet)
+                               bstrText = ::SysAllocString(T2OLE(lpstrText));
+                       delete [] lpstrText;
+               }
+
+               return (bstrText != NULL) ? TRUE : FALSE;
+       }
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       BOOL GetItemText(int nIndex, _CSTRING_NS::CString& strText) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               COMBOBOXEXITEM cbex = { 0 };
+               cbex.mask = CBEIF_TEXT;
+               cbex.iItem = nIndex;
+
+               strText.Empty();
+               BOOL bRet = FALSE;
+               for(int nLen = 256; ; nLen *= 2)
+               {
+                       cbex.pszText = strText.GetBufferSetLength(nLen);
+                       if(cbex.pszText == NULL)
+                       {
+                               bRet = FALSE;
+                               break;
+                       }
+                       cbex.cchTextMax = nLen;
+                       bRet = (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
+                       if(!bRet || (lstrlen(cbex.pszText) < nLen - 1))
+                               break;
+               }
+               strText.ReleaseBuffer();
+               return bRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       BOOL SetItemText(int nIndex, LPCTSTR lpszItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return SetItem(nIndex, CBEIF_TEXT, lpszItem, 0, 0, 0, 0, 0);
+       }
+
+       CComboBox GetComboCtrl() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CComboBox((HWND)::SendMessage(m_hWnd, CBEM_GETCOMBOCONTROL, 0, 0L));
+       }
+
+       CEdit GetEditCtrl() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CEdit((HWND)::SendMessage(m_hWnd, CBEM_GETEDITCONTROL, 0, 0L));
+       }
+
+       BOOL HasEditChanged() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, CBEM_HASEDITCHANGED, 0, 0L);
+       }
+
+// Non-functional
+       int AddString(LPCTSTR /*lpszItem*/)
+       {
+               ATLASSERT(FALSE);  // Not available in CComboBoxEx; use InsertItem
+               return 0;
+       }
+
+       int InsertString(int /*nIndex*/, LPCTSTR /*lpszString*/)
+       {
+               ATLASSERT(FALSE);  // Not available in CComboBoxEx; use InsertItem
+               return 0;
+       }
+
+       int Dir(UINT /*attr*/, LPCTSTR /*lpszWildCard*/)
+       {
+               ATLASSERT(FALSE);  // Not available in CComboBoxEx
+               return 0;
+       }
+
+       int FindString(int /*nStartAfter*/, LPCTSTR /*lpszString*/) const
+       {
+               ATLASSERT(FALSE);  // Not available in CComboBoxEx; try FindStringExact
+               return 0;
+       }
+};
+
+typedef CComboBoxExT<ATL::CWindow>   CComboBoxEx;
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMonthCalendarCtrl
+
+template <class TBase>
+class CMonthCalendarCtrlT : public TBase
+{
+public:
+// Constructors
+       CMonthCalendarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CMonthCalendarCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return MONTHCAL_CLASS;
+       }
+
+       COLORREF GetColor(int nColorType) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, MCM_GETCOLOR, nColorType, 0L);
+       }
+
+       COLORREF SetColor(int nColorType, COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, MCM_SETCOLOR, nColorType, clr);
+       }
+
+       BOOL GetCurSel(LPSYSTEMTIME lpSysTime) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_GETCURSEL, 0, (LPARAM)lpSysTime);
+       }
+
+       BOOL SetCurSel(LPSYSTEMTIME lpSysTime)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_SETCURSEL, 0, (LPARAM)lpSysTime);
+       }
+
+       int GetFirstDayOfWeek(BOOL* pbLocaleVal = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, MCM_GETFIRSTDAYOFWEEK, 0, 0L);
+               if(pbLocaleVal != NULL)
+                       *pbLocaleVal = (BOOL)HIWORD(dwRet);
+               return (int)(short)LOWORD(dwRet);
+       }
+
+       int SetFirstDayOfWeek(int nDay, BOOL* pbLocaleVal = NULL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               DWORD dwRet = (DWORD)::SendMessage(m_hWnd, MCM_SETFIRSTDAYOFWEEK, 0, nDay);
+               if(pbLocaleVal != NULL)
+                       *pbLocaleVal = (BOOL)HIWORD(dwRet);
+               return (int)(short)LOWORD(dwRet);
+       }
+
+       int GetMaxSelCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, MCM_GETMAXSELCOUNT, 0, 0L);
+       }
+
+       BOOL SetMaxSelCount(int nMax)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_SETMAXSELCOUNT, nMax, 0L);
+       }
+
+       int GetMonthDelta() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, MCM_GETMONTHDELTA, 0, 0L);
+       }
+
+       int SetMonthDelta(int nDelta)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, MCM_SETMONTHDELTA, nDelta, 0L);
+       }
+
+       DWORD GetRange(LPSYSTEMTIME lprgSysTimeArray) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, MCM_GETRANGE, 0, (LPARAM)lprgSysTimeArray);
+       }
+
+       BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_SETRANGE, dwFlags, (LPARAM)lprgSysTimeArray);
+       }
+
+       BOOL GetSelRange(LPSYSTEMTIME lprgSysTimeArray) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_GETSELRANGE, 0, (LPARAM)lprgSysTimeArray);
+       }
+
+       BOOL SetSelRange(LPSYSTEMTIME lprgSysTimeArray)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_SETSELRANGE, 0, (LPARAM)lprgSysTimeArray);
+       }
+
+       BOOL GetToday(LPSYSTEMTIME lpSysTime) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_GETTODAY, 0, (LPARAM)lpSysTime);
+       }
+
+       void SetToday(LPSYSTEMTIME lpSysTime)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, MCM_SETTODAY, 0, (LPARAM)lpSysTime);
+       }
+
+       BOOL GetMinReqRect(LPRECT lpRectInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_GETMINREQRECT, 0, (LPARAM)lpRectInfo);
+       }
+
+       int GetMaxTodayWidth() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, MCM_GETMAXTODAYWIDTH, 0, 0L);
+       }
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       BOOL GetUnicodeFormat() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_GETUNICODEFORMAT, 0, 0L);
+       }
+
+       BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_SETUNICODEFORMAT, bUnicode, 0L);
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+       DWORD GetCurrentView() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, MCM_GETCURRENTVIEW, 0, 0L);
+       }
+
+       BOOL SetCurrentView(DWORD dwView)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_SETCURRENTVIEW, 0, dwView);
+       }
+
+       DWORD GetCalendarCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, MCM_GETCALENDARCOUNT, 0, 0L);
+       }
+
+       BOOL GetCalendarGridInfo(PMCGRIDINFO pGridInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_GETCALENDARGRIDINFO, 0, (LPARAM)pGridInfo);
+       }
+
+       CALID GetCALID() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (CALID)::SendMessage(m_hWnd, MCM_GETCALID, 0, 0L);
+       }
+
+       void SetCALID(CALID calid)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, MCM_SETCALID, (LPARAM)calid, 0L);
+       }
+
+       int GetCalendarBorder() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, MCM_GETCALENDARBORDER, 0, 0L);
+       }
+
+       void SetCalendarBorder(int cxyBorder, BOOL bSet = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, MCM_SETCALENDARBORDER, (WPARAM)bSet, (LPARAM)cxyBorder);
+       }
+#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+
+// Operations
+       int GetMonthRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, MCM_GETMONTHRANGE, dwFlags, (LPARAM)lprgSysTimeArray);
+       }
+
+       BOOL SetDayState(int nMonths, LPMONTHDAYSTATE lpDayStateArray)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, MCM_SETDAYSTATE, nMonths, (LPARAM)lpDayStateArray);
+       }
+
+       DWORD HitTest(PMCHITTESTINFO pMCHitTest) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, MCM_HITTEST, 0, (LPARAM)pMCHitTest);
+       }
+
+#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+       void SizeRectToMin(LPRECT lpRect)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, MCM_SIZERECTTOMIN, 0, (LPARAM)lpRect);
+       }
+#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+};
+
+typedef CMonthCalendarCtrlT<ATL::CWindow>   CMonthCalendarCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDateTimePickerCtrl
+
+template <class TBase>
+class CDateTimePickerCtrlT : public TBase
+{
+public:
+// Constructors
+       CDateTimePickerCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CDateTimePickerCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Operations
+       static LPCTSTR GetWndClassName()
+       {
+               return DATETIMEPICK_CLASS;
+       }
+
+       BOOL SetFormat(LPCTSTR lpszFormat)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, DTM_SETFORMAT, 0, (LPARAM)lpszFormat);
+       }
+
+       COLORREF GetMonthCalColor(int nColorType) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, DTM_GETMCCOLOR, nColorType, 0L);
+       }
+
+       COLORREF SetMonthCalColor(int nColorType, COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, DTM_SETMCCOLOR, nColorType, clr);
+       }
+
+       DWORD GetRange(LPSYSTEMTIME lpSysTimeArray) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, DTM_GETRANGE, 0, (LPARAM)lpSysTimeArray);
+       }
+
+       BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lpSysTimeArray)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, DTM_SETRANGE, dwFlags, (LPARAM)lpSysTimeArray);
+       }
+
+       DWORD GetSystemTime(LPSYSTEMTIME lpSysTime) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)lpSysTime);
+       }
+
+       BOOL SetSystemTime(DWORD dwFlags, LPSYSTEMTIME lpSysTime)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, DTM_SETSYSTEMTIME, dwFlags, (LPARAM)lpSysTime);
+       }
+
+       CMonthCalendarCtrl GetMonthCal() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CMonthCalendarCtrl((HWND)::SendMessage(m_hWnd, DTM_GETMONTHCAL, 0, 0L));
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       CFontHandle GetMonthCalFont() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CFontHandle((HFONT)::SendMessage(m_hWnd, DTM_GETMCFONT, 0, 0L));
+       }
+
+       void SetMonthCalFont(HFONT hFont, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_SETMCFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0));
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+       DWORD GetMonthCalStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, DTM_GETMCSTYLE, 0, 0L);
+       }
+
+       DWORD SetMonthCalStyle(DWORD dwStyle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, DTM_SETMCSTYLE, 0, (LPARAM)dwStyle);
+       }
+
+       void GetDateTimePickerInfo(LPDATETIMEPICKERINFO lpPickerInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_GETDATETIMEPICKERINFO, 0, (LPARAM)lpPickerInfo);
+       }
+
+       BOOL GetIdealSize(LPSIZE lpSize) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, DTM_GETIDEALSIZE, 0, (LPARAM)lpSize);
+       }
+
+       void CloseMonthCal()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_CLOSEMONTHCAL, 0, 0L);
+       }
+#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+};
+
+typedef CDateTimePickerCtrlT<ATL::CWindow>   CDateTimePickerCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CFlatScrollBarImpl - support for flat scroll bars
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+template <class T>
+class CFlatScrollBarImpl
+{
+public:
+// Initialization
+       BOOL FlatSB_Initialize()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::InitializeFlatSB(pT->m_hWnd);
+       }
+
+       HRESULT FlatSB_Uninitialize()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::UninitializeFlatSB(pT->m_hWnd);
+       }
+
+// Flat scroll bar properties
+       BOOL FlatSB_GetScrollProp(UINT uIndex, LPINT lpnValue) const
+       {
+               const T* pT = static_cast<const T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_GetScrollProp(pT->m_hWnd, uIndex, lpnValue);
+       }
+
+       BOOL FlatSB_SetScrollProp(UINT uIndex, int nValue, BOOL bRedraw = TRUE)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_SetScrollProp(pT->m_hWnd, uIndex, nValue, bRedraw);
+       }
+
+// Attributes
+       int FlatSB_GetScrollPos(int nBar) const
+       {
+               const T* pT = static_cast<const T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_GetScrollPos(pT->m_hWnd, nBar);
+       }
+
+       int FlatSB_SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_SetScrollPos(pT->m_hWnd, nBar, nPos, bRedraw);
+       }
+
+       BOOL FlatSB_GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
+       {
+               const T* pT = static_cast<const T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_GetScrollRange(pT->m_hWnd, nBar, lpMinPos, lpMaxPos);
+       }
+
+       BOOL FlatSB_SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_SetScrollRange(pT->m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
+       }
+
+       BOOL FlatSB_GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) const
+       {
+               const T* pT = static_cast<const T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_GetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo);
+       }
+
+       int FlatSB_SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_SetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo, bRedraw);
+       }
+
+// Operations
+       BOOL FlatSB_ShowScrollBar(UINT nBar, BOOL bShow = TRUE)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_ShowScrollBar(pT->m_hWnd, nBar, bShow);
+       }
+
+       BOOL FlatSB_EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::FlatSB_EnableScrollBar(pT->m_hWnd, uSBFlags, uArrowFlags);
+       }
+};
+
+template <class TBase>
+class CFlatScrollBarT : public TBase, public CFlatScrollBarImpl<CFlatScrollBarT< TBase > >
+{
+public:
+       CFlatScrollBarT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CFlatScrollBarT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+};
+
+typedef CFlatScrollBarT<ATL::CWindow>   CFlatScrollBar;
+
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CIPAddressCtrl
+
+#if (_WIN32_IE >= 0x0400)
+
+template <class TBase>
+class CIPAddressCtrlT : public TBase
+{
+public:
+// Constructors
+       CIPAddressCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CIPAddressCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Atteributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_IPADDRESS;
+       }
+
+       BOOL IsBlank() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, IPM_ISBLANK, 0, 0L);
+       }
+
+       int GetAddress(LPDWORD lpdwAddress) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, IPM_GETADDRESS, 0, (LPARAM)lpdwAddress);
+       }
+
+       void SetAddress(DWORD dwAddress)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IPM_SETADDRESS, 0, dwAddress);
+       }
+
+       void ClearAddress()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IPM_CLEARADDRESS, 0, 0L);
+       }
+
+       void SetRange(int nField, WORD wRange)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IPM_SETRANGE, nField, wRange);
+       }
+
+       void SetRange(int nField, BYTE nMin, BYTE nMax)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IPM_SETRANGE, nField, MAKEIPRANGE(nMin, nMax));
+       }
+
+       void SetFocus(int nField)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IPM_SETFOCUS, nField, 0L);
+       }
+};
+
+typedef CIPAddressCtrlT<ATL::CWindow>   CIPAddressCtrl;
+
+#endif // (_WIN32_IE >= 0x0400)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPagerCtrl
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+template <class TBase>
+class CPagerCtrlT : public TBase
+{
+public:
+// Constructors
+       CPagerCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CPagerCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_PAGESCROLLER;
+       }
+
+       int GetButtonSize() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PGM_GETBUTTONSIZE, 0, 0L);
+       }
+
+       int SetButtonSize(int nButtonSize)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PGM_SETBUTTONSIZE, 0, nButtonSize);
+       }
+
+       DWORD GetButtonState(int nButton) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nButton == PGB_TOPORLEFT || nButton == PGB_BOTTOMORRIGHT);
+               return (DWORD)::SendMessage(m_hWnd, PGM_GETBUTTONSTATE, 0, nButton);
+       }
+
+       COLORREF GetBkColor() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, PGM_GETBKCOLOR, 0, 0L);
+       }
+
+       COLORREF SetBkColor(COLORREF clrBk)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (COLORREF)::SendMessage(m_hWnd, PGM_SETBKCOLOR, 0, (LPARAM)clrBk);
+       }
+
+       int GetBorder() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PGM_GETBORDER, 0, 0L);
+       }
+
+       int SetBorder(int nBorderSize)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PGM_SETBORDER, 0, nBorderSize);
+       }
+
+       int GetPos() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PGM_GETPOS, 0, 0L);
+       }
+
+       int SetPos(int nPos)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PGM_SETPOS, 0, nPos);
+       }
+
+// Operations
+       void SetChild(HWND hWndChild)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PGM_SETCHILD, 0, (LPARAM)hWndChild);
+       }
+
+       void ForwardMouse(BOOL bForward = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PGM_FORWARDMOUSE, bForward, 0L);
+       }
+
+       void RecalcSize()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PGM_RECALCSIZE, 0, 0L);
+       }
+
+       void GetDropTarget(IDropTarget** ppDropTarget)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(ppDropTarget != NULL);
+               ::SendMessage(m_hWnd, PGM_GETDROPTARGET, 0, (LPARAM)ppDropTarget);
+       }
+};
+
+typedef CPagerCtrlT<ATL::CWindow>   CPagerCtrl;
+
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CLinkCtrl - Windows SYSLINK control
+
+#if (_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)
+
+template <class TBase>
+class CLinkCtrlT : public TBase
+{
+public:
+// Constructors
+       CLinkCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CLinkCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+#ifdef _UNICODE
+               return WC_LINK;
+#else // !_UNICODE
+               return "SysLink";
+#endif // !_UNICODE
+       }
+
+       int GetIdealHeight(int cxMaxWidth = 0) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LM_GETIDEALHEIGHT, cxMaxWidth, 0L);
+       }
+
+       BOOL GetItem(PLITEM pLItem) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LM_GETITEM, 0, (LPARAM)pLItem);
+       }
+
+       BOOL SetItem(PLITEM pLItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LM_SETITEM, 0, (LPARAM)pLItem);
+       }
+
+       // Vista only
+       int GetIdealSize(SIZE& size, int cxMaxWidth = 0) const
+       {
+#ifndef LM_GETIDEALSIZE
+               const UINT LM_GETIDEALSIZE = LM_GETIDEALHEIGHT;
+#endif
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, LM_GETIDEALSIZE, cxMaxWidth, (LPARAM)&size);
+       }
+
+// Operations
+       BOOL HitTest(PLHITTESTINFO pLHitTestInfo) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, LM_HITTEST, 0, (LPARAM)pLHitTestInfo);
+       }
+};
+
+typedef CLinkCtrlT<ATL::CWindow>   CLinkCtrl;
+
+#endif // (_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CCustomDraw - MI class for custom-draw support
+
+template <class T>
+class CCustomDraw
+{
+public:
+#if (_ATL_VER < 0x0700)
+       BOOL m_bHandledCD;
+
+       BOOL IsMsgHandled() const
+       {
+               return m_bHandledCD;
+       }
+
+       void SetMsgHandled(BOOL bHandled)
+       {
+               m_bHandledCD = bHandled;
+       }
+#endif // !(_ATL_VER < 0x0700)
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CCustomDraw< T >)
+               NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
+       ALT_MSG_MAP(1)
+               REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
+       END_MSG_MAP()
+
+// message handler
+       LRESULT OnCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetMsgHandled(TRUE);
+               LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW)pnmh;
+               DWORD dwRet = 0;
+               switch(lpNMCustomDraw->dwDrawStage)
+               {
+               case CDDS_PREPAINT:
+                       dwRet = pT->OnPrePaint(idCtrl, lpNMCustomDraw);
+                       break;
+               case CDDS_POSTPAINT:
+                       dwRet = pT->OnPostPaint(idCtrl, lpNMCustomDraw);
+                       break;
+               case CDDS_PREERASE:
+                       dwRet = pT->OnPreErase(idCtrl, lpNMCustomDraw);
+                       break;
+               case CDDS_POSTERASE:
+                       dwRet = pT->OnPostErase(idCtrl, lpNMCustomDraw);
+                       break;
+               case CDDS_ITEMPREPAINT:
+                       dwRet = pT->OnItemPrePaint(idCtrl, lpNMCustomDraw);
+                       break;
+               case CDDS_ITEMPOSTPAINT:
+                       dwRet = pT->OnItemPostPaint(idCtrl, lpNMCustomDraw);
+                       break;
+               case CDDS_ITEMPREERASE:
+                       dwRet = pT->OnItemPreErase(idCtrl, lpNMCustomDraw);
+                       break;
+               case CDDS_ITEMPOSTERASE:
+                       dwRet = pT->OnItemPostErase(idCtrl, lpNMCustomDraw);
+                       break;
+#if (_WIN32_IE >= 0x0400)
+               case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
+                       dwRet = pT->OnSubItemPrePaint(idCtrl, lpNMCustomDraw);
+                       break;
+#endif // (_WIN32_IE >= 0x0400)
+               default:
+                       pT->SetMsgHandled(FALSE);
+                       break;
+               }
+               bHandled = pT->IsMsgHandled();
+               return dwRet;
+       }
+
+// Overrideables
+       DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+
+       DWORD OnPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+
+       DWORD OnPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+
+       DWORD OnPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+
+       DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+
+       DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+
+       DWORD OnItemPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+
+       DWORD OnItemPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_DODEFAULT;
+       }
+#endif // (_WIN32_IE >= 0x0400)
+};
+
+
+// --- Windows CE common controls ---
+
+#ifdef _WIN32_WCE
+
+///////////////////////////////////////////////////////////////////////////////
+// CCECommandBarCtrl
+
+template <class TBase>
+class CCECommandBarCtrlT : public TBase
+{
+public:
+// Constructors
+       CCECommandBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) { }
+
+       CCECommandBarCtrlT< TBase >& operator=(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Attributes
+       BOOL IsVisible() const
+       {
+               return IsWindowVisible();
+       }
+
+       int GetHeight() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_Height(m_hWnd);
+       }
+
+       HMENU GetMenu(WORD wButton) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_GetMenu(m_hWnd, wButton);
+       }
+
+// Operations
+       HWND Create(HWND hWndParent, int nCmdBarID)
+       {
+               m_hWnd = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), hWndParent, nCmdBarID);
+               ATLASSERT(::IsWindow(m_hWnd));
+               return m_hWnd;
+       }
+
+       void Destroy()
+       {
+               DestroyWindow();
+       }
+
+       BOOL Show(BOOL bShow = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_Show(m_hWnd, bShow);
+       }
+
+       BOOL DrawMenuBar(WORD wButton)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_DrawMenuBar(m_hWnd, wButton);
+       }
+
+       BOOL AddAdornments(DWORD dwFlags = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_AddAdornments(m_hWnd, dwFlags, 0);
+       }
+
+       int AddBitmap(int nBitmapID, int nNumImages)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_AddBitmap(m_hWnd, ModuleHelper::GetResourceInstance(), nBitmapID, nNumImages, 16, 16);
+       }
+
+       BOOL AddButtons(UINT uNumButtons, LPTBBUTTON lpButtons)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CommandBar_AddButtons(m_hWnd, uNumButtons, lpButtons);
+       }
+
+       BOOL AddToolTips(UINT uNumToolTips, LPTSTR lpToolTips)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CommandBar_AddToolTips(m_hWnd, uNumToolTips, lpToolTips);
+       }
+
+       BOOL InsertButton(int nButton, LPTBBUTTON lpButton)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CommandBar_InsertButton(m_hWnd, nButton, lpButton);
+       }
+
+       HWND InsertComboBox(int nWidth, UINT dwStyle, WORD wComboBoxID, WORD wButton)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_InsertComboBox(m_hWnd, ModuleHelper::GetModuleInstance(), nWidth, dwStyle, wComboBoxID, wButton);
+       }
+
+       BOOL InsertMenubar(WORD wMenuID, WORD wButton)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_InsertMenubar(m_hWnd, ModuleHelper::GetResourceInstance(), wMenuID, wButton);
+       }
+
+       BOOL InsertMenubarEx(ATL::_U_STRINGorID menu, WORD wButton)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBar_InsertMenubarEx(m_hWnd, ModuleHelper::GetResourceInstance(), (LPTSTR)menu.m_lpstr, wButton);
+       }
+
+       BOOL IsCommandBarMessage(LPMSG lpMsg)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::IsCommandBarMessage(m_hWnd, lpMsg);
+       }
+};
+
+#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC MenuBar
+       typedef CCECommandBarCtrlT<CToolBarCtrl>        CMenuBarCtrl;
+#else
+       typedef CCECommandBarCtrlT<CToolBarCtrl>        CCECommandBarCtrl;
+#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
+
+///////////////////////////////////////////////////////////////////////////////
+// CCECommandBandsCtrl
+
+template <class TBase>
+class CCECommandBandsCtrlT : public TBase
+{
+public:
+// Constructors
+       CCECommandBandsCtrlT(HWND hWnd = NULL) : TBase(hWnd) { }
+
+       CCECommandBandsCtrlT< TBase >& operator=(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Attributes
+       BOOL IsVisible() const
+       {
+               return IsWindowVisible();
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       UINT GetHeight() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CommandBands_Height(m_hWnd);
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+       HWND GetCommandBar(UINT uBand) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBands_GetCommandBar(m_hWnd, uBand);
+       }
+
+       BOOL GetRestoreInformation(UINT uBand, LPCOMMANDBANDSRESTOREINFO pcbr) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBands_GetRestoreInformation(m_hWnd, uBand, pcbr);
+       }
+
+// Operations
+       HWND Create(HWND hWndParent, UINT wID, DWORD dwStyles, HIMAGELIST hImageList = NULL)
+       {
+               m_hWnd = ::CommandBands_Create(ModuleHelper::GetModuleInstance(), hWndParent, wID, dwStyles, hImageList);
+               ATLASSERT(::IsWindow(m_hWnd));
+               return m_hWnd;
+       }
+
+       BOOL AddAdornments(DWORD dwFlags = 0, LPREBARBANDINFO prbbi = NULL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBands_AddAdornments(m_hWnd, ModuleHelper::GetModuleInstance(), dwFlags, prbbi);
+       }
+
+       BOOL AddBands(UINT uBandCount, LPREBARBANDINFO prbbi)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBands_AddBands(m_hWnd, ModuleHelper::GetModuleInstance(), uBandCount, prbbi);
+       }
+
+       BOOL Show(BOOL bShow = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::CommandBands_Show(m_hWnd, bShow);
+       }
+};
+
+typedef CCECommandBandsCtrlT<ATL::CWindow>     CCECommandBandsCtrl;
+
+#endif // _WIN32_WCE
+
+}; // namespace WTL
+
+#endif // __ATLCTRLS_H__
diff --git a/include/WTL/Include/atlctrlw.h b/include/WTL/Include/atlctrlw.h
new file mode 100644 (file)
index 0000000..ef75f12
--- /dev/null
@@ -0,0 +1,4161 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLCTRLW_H__
+#define __ATLCTRLW_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifdef _WIN32_WCE
+       #error atlctrlw.h is not supported on Windows CE
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlctrlw.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLCTRLS_H__
+       #error atlctrlw.h requires atlctrls.h to be included first
+#endif
+
+#if (_WIN32_IE < 0x0400)
+       #error atlctrlw.h requires _WIN32_IE >= 0x0400
+#endif
+
+// Define _WTL_CMDBAR_VISTA_MENUS as 0 to exclude Vista menus support
+#if !defined(_WTL_CMDBAR_VISTA_MENUS) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
+  #define _WTL_CMDBAR_VISTA_MENUS 1
+#endif
+
+#if _WTL_CMDBAR_VISTA_MENUS
+  #if !((_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501))
+       #error _WTL_CMDBAR_VISTA_MENUS requires (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
+  #endif
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CCommandBarCtrlImpl<T, TBase, TWinTraits>
+// CCommandBarCtrl
+// CMDICommandBarCtrlImpl<T, TBase, TWinTraits>
+// CMDICommandBarCtrl
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// Command Bars
+
+// Window Styles:
+#define CBRWS_TOP              CCS_TOP
+#define CBRWS_BOTTOM           CCS_BOTTOM
+#define CBRWS_NORESIZE         CCS_NORESIZE
+#define CBRWS_NOPARENTALIGN    CCS_NOPARENTALIGN
+#define CBRWS_NODIVIDER                CCS_NODIVIDER
+
+// Extended styles
+#define CBR_EX_TRANSPARENT     0x00000001L
+#define CBR_EX_SHAREMENU       0x00000002L
+#define CBR_EX_ALTFOCUSMODE    0x00000004L
+#define CBR_EX_TRACKALWAYS     0x00000008L
+#define CBR_EX_NOVISTAMENUS    0x00000010L
+
+// standard command bar styles
+#define ATL_SIMPLE_CMDBAR_PANE_STYLE \
+       (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBRWS_NODIVIDER | CBRWS_NORESIZE | CBRWS_NOPARENTALIGN)
+
+// Messages - support chevrons for frame windows
+#define CBRM_GETCMDBAR                 (WM_USER + 301) // returns command bar HWND
+#define CBRM_GETMENU                   (WM_USER + 302) // returns loaded or attached menu
+#define CBRM_TRACKPOPUPMENU            (WM_USER + 303) // displays a popup menu
+
+typedef struct tagCBRPOPUPMENU
+{
+       int cbSize;
+       HMENU hMenu;         // popup menu do display
+       UINT uFlags;         // TPM_* flags for ::TrackPopupMenuEx
+       int x;
+       int y;
+       LPTPMPARAMS lptpm;   // ptr to TPMPARAMS for ::TrackPopupMenuEx
+} CBRPOPUPMENU, *LPCBRPOPUPMENU;
+
+// helper class
+template <class T>
+class CSimpleStack : public ATL::CSimpleArray< T >
+{
+public:
+       BOOL Push(T t)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-PUSH (%8.8X) size = %i\n"), t, GetSize());
+#endif
+               return Add(t);
+       }
+
+       T Pop()
+       {
+               int nLast = GetSize() - 1;
+               if(nLast < 0)
+                       return NULL;   // must be able to convert to NULL
+               T t = m_aT[nLast];
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-POP (%8.8X) size = %i\n"), t, GetSize());
+#endif
+               if(!RemoveAt(nLast))
+                       return NULL;
+               return t;
+       }
+
+       T GetCurrent()
+       {
+               int nLast = GetSize() - 1;
+               if(nLast < 0)
+                       return NULL;   // must be able to convert to NULL
+               return m_aT[nLast];
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CCommandBarCtrlBase - base class for the Command Bar implementation
+
+class CCommandBarCtrlBase : public CToolBarCtrl
+{
+public:
+       struct _MsgHookData
+       {
+               HHOOK hMsgHook;
+               DWORD dwUsage;
+
+               _MsgHookData() : hMsgHook(NULL), dwUsage(0)
+               { }
+       };
+
+       typedef ATL::CSimpleMap<DWORD, _MsgHookData*>   CMsgHookMap;
+       static CMsgHookMap* s_pmapMsgHook;
+
+       static HHOOK s_hCreateHook;
+       static bool s_bW2K;  // For animation flag
+       static CCommandBarCtrlBase* s_pCurrentBar;
+       static bool s_bStaticInit;
+
+       CSimpleStack<HWND> m_stackMenuWnd;
+       CSimpleStack<HMENU> m_stackMenuHandle;
+
+       HWND m_hWndHook;
+       DWORD m_dwMagic;
+
+
+       CCommandBarCtrlBase() : m_hWndHook(NULL), m_dwMagic(1314)
+       {
+               // init static variables
+               if(!s_bStaticInit)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlBase::CCommandBarCtrlBase.\n"));
+                               ATLASSERT(FALSE);
+                               return;
+                       }
+
+                       if(!s_bStaticInit)
+                       {
+                               // Just in case...
+                               AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);
+                               // Animation on Win2000 only
+                               s_bW2K = !AtlIsOldWindows();
+                               // done
+                               s_bStaticInit = true;
+                       }
+
+                       lock.Unlock();
+               }
+       }
+
+       bool IsCommandBarBase() const { return m_dwMagic == 1314; }
+};
+
+__declspec(selectany) CCommandBarCtrlBase::CMsgHookMap* CCommandBarCtrlBase::s_pmapMsgHook = NULL;
+__declspec(selectany) HHOOK CCommandBarCtrlBase::s_hCreateHook = NULL;
+__declspec(selectany) CCommandBarCtrlBase* CCommandBarCtrlBase::s_pCurrentBar = NULL;
+__declspec(selectany) bool CCommandBarCtrlBase::s_bW2K = false;
+__declspec(selectany) bool CCommandBarCtrlBase::s_bStaticInit = false;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CCommandBarCtrl - ATL implementation of Command Bars
+
+template <class T, class TBase = CCommandBarCtrlBase, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CCommandBarCtrlImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >
+{
+public:
+       DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
+
+// Declarations
+       struct _MenuItemData    // menu item data
+       {
+               DWORD dwMagic;
+               LPTSTR lpstrText;
+               UINT fType;
+               UINT fState;
+               int iButton;
+
+               _MenuItemData() { dwMagic = 0x1313; }
+               bool IsCmdBarMenuItem() { return (dwMagic == 0x1313); }
+       };
+
+       struct _ToolBarData     // toolbar resource data
+       {
+               WORD wVersion;
+               WORD wWidth;
+               WORD wHeight;
+               WORD wItemCount;
+               //WORD aItems[wItemCount]
+
+               WORD* items()
+                       { return (WORD*)(this+1); }
+       };
+
+// Constants
+       enum _CmdBarDrawConstants
+       {
+               s_kcxGap = 1,
+               s_kcxTextMargin = 2,
+               s_kcxButtonMargin = 3,
+               s_kcyButtonMargin = 3
+       };
+
+       enum
+       {
+               _nMaxMenuItemTextLength = 100,
+               _chChevronShortcut = _T('/')
+       };
+
+#ifndef DT_HIDEPREFIX
+       enum { DT_HIDEPREFIX = 0x00100000 };
+#endif // !DT_HIDEPREFIX
+
+// Data members
+       HMENU m_hMenu;
+       HIMAGELIST m_hImageList;
+       ATL::CSimpleValArray<WORD> m_arrCommand;
+
+       DWORD m_dwExtendedStyle;   // Command Bar specific extended styles
+
+       ATL::CContainedWindow m_wndParent;
+
+       bool m_bMenuActive:1;
+       bool m_bAttachedMenu:1;
+       bool m_bImagesVisible:1;
+       bool m_bPopupItem:1;
+       bool m_bContextMenu:1;
+       bool m_bEscapePressed:1;
+       bool m_bSkipMsg:1;
+       bool m_bParentActive:1;
+       bool m_bFlatMenus:1;
+       bool m_bUseKeyboardCues:1;
+       bool m_bShowKeyboardCues:1;
+       bool m_bAllowKeyboardCues:1;
+       bool m_bKeyboardInput:1;
+       bool m_bAlphaImages:1;
+       bool m_bLayoutRTL:1;
+       bool m_bSkipPostDown:1;
+       bool m_bVistaMenus:1;
+
+       int m_nPopBtn;
+       int m_nNextPopBtn;
+
+       SIZE m_szBitmap;
+       SIZE m_szButton;
+
+       COLORREF m_clrMask;
+       CFont m_fontMenu;   // used internally, only to measure text
+
+       UINT m_uSysKey;
+
+       HWND m_hWndFocus;   // Alternate focus mode
+
+       int m_cxExtraSpacing;
+
+#if _WTL_CMDBAR_VISTA_MENUS
+       ATL::CSimpleValArray<HBITMAP> m_arrVistaBitmap;   // Bitmaps for Vista menus
+#endif // _WTL_CMDBAR_VISTA_MENUS
+
+// Constructor/destructor
+       CCommandBarCtrlImpl() : 
+                       m_hMenu(NULL), 
+                       m_hImageList(NULL), 
+                       m_wndParent(this, 1), 
+                       m_bMenuActive(false), 
+                       m_bAttachedMenu(false), 
+                       m_nPopBtn(-1), 
+                       m_nNextPopBtn(-1), 
+                       m_bPopupItem(false),
+                       m_bImagesVisible(true),
+                       m_bSkipMsg(false),
+                       m_uSysKey(0),
+                       m_hWndFocus(NULL),
+                       m_bContextMenu(false),
+                       m_bEscapePressed(false),
+                       m_clrMask(RGB(192, 192, 192)),
+                       m_dwExtendedStyle(CBR_EX_TRANSPARENT | CBR_EX_SHAREMENU | CBR_EX_TRACKALWAYS),
+                       m_bParentActive(true),
+                       m_bFlatMenus(false),
+                       m_bUseKeyboardCues(false),
+                       m_bShowKeyboardCues(false),
+                       m_bAllowKeyboardCues(true),
+                       m_bKeyboardInput(false),
+                       m_cxExtraSpacing(0),
+                       m_bAlphaImages(false),
+                       m_bLayoutRTL(false),
+                       m_bSkipPostDown(false),
+                       m_bVistaMenus(false)
+       {
+               SetImageSize(16, 15);   // default
+       }
+
+       ~CCommandBarCtrlImpl()
+       {
+               if(m_wndParent.IsWindow())
+/*scary!*/                     m_wndParent.UnsubclassWindow();
+
+               if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) == 0)
+                       ::DestroyMenu(m_hMenu);
+
+               if(m_hImageList != NULL)
+                       ::ImageList_Destroy(m_hImageList);
+       }
+
+// Attributes
+       DWORD GetCommandBarExtendedStyle() const
+       {
+               return m_dwExtendedStyle;
+       }
+
+       DWORD SetCommandBarExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
+       {
+               DWORD dwPrevStyle = m_dwExtendedStyle;
+               if(dwMask == 0)
+                       m_dwExtendedStyle = dwExtendedStyle;
+               else
+                       m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
+               return dwPrevStyle;
+       }
+
+       CMenuHandle GetMenu() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return m_hMenu;
+       }
+
+       COLORREF GetImageMaskColor() const
+       {
+               return m_clrMask;
+       }
+
+       COLORREF SetImageMaskColor(COLORREF clrMask)
+       {
+               COLORREF clrOld = m_clrMask;
+               m_clrMask = clrMask;
+               return clrOld;
+       }
+
+       bool GetImagesVisible() const
+       {
+               return m_bImagesVisible;
+       }
+
+       bool SetImagesVisible(bool bVisible)
+       {
+               bool bOld = m_bImagesVisible;
+               m_bImagesVisible = bVisible;
+               return bOld;
+       }
+
+       void GetImageSize(SIZE& size) const
+       {
+               size = m_szBitmap;
+       }
+
+       bool SetImageSize(SIZE& size)
+       {
+               return SetImageSize(size.cx, size.cy);
+       }
+
+       bool SetImageSize(int cx, int cy)
+       {
+               if(m_hImageList != NULL)
+               {
+                       if(::ImageList_GetImageCount(m_hImageList) == 0)   // empty
+                       {
+                               ::ImageList_Destroy(m_hImageList);
+                               m_hImageList = NULL;
+                       }
+                       else
+                       {
+                               return false;   // can't set, image list exists
+                       }
+               }
+
+               if(cx == 0 || cy == 0)
+                       return false;
+
+               m_szBitmap.cx = cx;
+               m_szBitmap.cy = cy;
+               m_szButton.cx = m_szBitmap.cx + 2 * s_kcxButtonMargin;
+               m_szButton.cy = m_szBitmap.cy + 2 * s_kcyButtonMargin;
+
+               return true;
+       }
+
+       bool GetAlphaImages() const
+       {
+               return m_bAlphaImages;
+       }
+
+       bool SetAlphaImages(bool bAlphaImages)
+       {
+               if(m_hImageList != NULL)
+               {
+                       if(::ImageList_GetImageCount(m_hImageList) == 0)   // empty
+                       {
+                               ::ImageList_Destroy(m_hImageList);
+                               m_hImageList = NULL;
+                       }
+                       else
+                       {
+                               return false;   // can't set, image list exists
+                       }
+               }
+
+               m_bAlphaImages = bAlphaImages;
+               return true;
+       }
+
+       HWND GetCmdBar() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L);
+       }
+
+// Methods
+       HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       UINT nID = 0, LPVOID lpCreateParam = NULL)
+       {
+               // These styles are required for command bars
+               dwStyle |= TBSTYLE_LIST | TBSTYLE_FLAT;
+#if (_MSC_VER >= 1300)
+               return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
+#else // !(_MSC_VER >= 1300)
+               typedef ATL::CWindowImpl< T, TBase, TWinTraits >   _baseClass;
+               return _baseClass::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
+#endif // !(_MSC_VER >= 1300)
+       }
+
+       BOOL AttachToWindow(HWND hWnd)
+       {
+               ATLASSERT(m_hWnd == NULL);
+               ATLASSERT(::IsWindow(hWnd));
+               BOOL bRet = SubclassWindow(hWnd);
+               if(bRet)
+               {
+                       m_bAttachedMenu = true;
+                       T* pT = static_cast<T*>(this);
+                       pT->GetSystemSettings();
+               }
+               return bRet;
+       }
+
+       BOOL LoadMenu(ATL::_U_STRINGorID menu)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               if(m_bAttachedMenu)   // doesn't work in this mode
+                       return FALSE;
+               if(menu.m_lpstr == NULL)
+                       return FALSE;
+
+               HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr);
+               if(hMenu == NULL)
+                       return FALSE;
+
+               return AttachMenu(hMenu);
+       }
+
+       BOOL AttachMenu(HMENU hMenu)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hMenu == NULL || ::IsMenu(hMenu));
+               if(hMenu != NULL && !::IsMenu(hMenu))
+                       return FALSE;
+
+#if _WTL_CMDBAR_VISTA_MENUS
+               // remove Vista bitmaps if used
+               if(m_bVistaMenus && (m_hMenu != NULL))
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->_RemoveVistaBitmapsFromMenu();
+               }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+
+               // destroy old menu, if needed, and set new one
+               if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) == 0)
+                       ::DestroyMenu(m_hMenu);
+
+               m_hMenu = hMenu;
+
+               if(m_bAttachedMenu)   // Nothing else in this mode
+                       return TRUE;
+
+               // Build buttons according to menu
+               SetRedraw(FALSE);
+
+               // Clear all buttons
+               int nCount = GetButtonCount();
+               for(int i = 0; i < nCount; i++)
+                       ATLVERIFY(DeleteButton(0) != FALSE);
+
+               // Add buttons for each menu item
+               if(m_hMenu != NULL)
+               {
+                       int nItems = ::GetMenuItemCount(m_hMenu);
+
+                       T* pT = static_cast<T*>(this);
+                       pT;   // avoid level 4 warning
+                       TCHAR szString[pT->_nMaxMenuItemTextLength];
+                       for(int i = 0; i < nItems; i++)
+                       {
+                               CMenuItemInfo mii;
+                               mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU;
+                               mii.fType = MFT_STRING;
+                               mii.dwTypeData = szString;
+                               mii.cch = pT->_nMaxMenuItemTextLength;
+                               BOOL bRet = ::GetMenuItemInfo(m_hMenu, i, TRUE, &mii);
+                               ATLASSERT(bRet);
+                               // If we have more than the buffer, we assume we have bitmaps bits
+                               if(lstrlen(szString) > pT->_nMaxMenuItemTextLength - 1)
+                               {
+                                       mii.fType = MFT_BITMAP;
+                                       ::SetMenuItemInfo(m_hMenu, i, TRUE, &mii);
+                                       szString[0] = 0;
+                               }
+
+                               // NOTE: Command Bar currently supports only drop-down menu items
+                               ATLASSERT(mii.hSubMenu != NULL);
+
+                               TBBUTTON btn = { 0 };
+                               btn.iBitmap = 0;
+                               btn.idCommand = i;
+                               btn.fsState = (BYTE)(((mii.fState & MFS_DISABLED) == 0) ? TBSTATE_ENABLED : 0);
+                               btn.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE | TBSTYLE_DROPDOWN;
+                               btn.dwData = 0;
+                               btn.iString = 0;
+
+                               bRet = InsertButton(-1, &btn);
+                               ATLASSERT(bRet);
+
+                               TBBUTTONINFO bi = { 0 };
+                               bi.cbSize = sizeof(TBBUTTONINFO);
+                               bi.dwMask = TBIF_TEXT;
+                               bi.pszText = szString;
+
+                               bRet = SetButtonInfo(i, &bi);
+                               ATLASSERT(bRet);
+                       }
+               }
+
+               SetRedraw(TRUE);
+               Invalidate();
+               UpdateWindow();
+
+               return TRUE;
+       }
+
+       BOOL LoadImages(ATL::_U_STRINGorID image)
+       {
+               return _LoadImagesHelper(image, false);
+       }
+
+       BOOL LoadMappedImages(UINT nIDImage, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0)
+       {
+               return _LoadImagesHelper(nIDImage, true, nFlags , lpColorMap, nMapSize);
+       }
+
+       BOOL _LoadImagesHelper(ATL::_U_STRINGorID image, bool bMapped, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HINSTANCE hInstance = ModuleHelper::GetResourceInstance();
+
+               HRSRC hRsrc = ::FindResource(hInstance, image.m_lpstr, (LPTSTR)RT_TOOLBAR);
+               if(hRsrc == NULL)
+                       return FALSE;
+
+               HGLOBAL hGlobal = ::LoadResource(hInstance, hRsrc);
+               if(hGlobal == NULL)
+                       return FALSE;
+
+               _ToolBarData* pData = (_ToolBarData*)::LockResource(hGlobal);
+               if(pData == NULL)
+                       return FALSE;
+               ATLASSERT(pData->wVersion == 1);
+
+               WORD* pItems = pData->items();
+               int nItems = pData->wItemCount;
+
+               // Set internal data
+               SetImageSize(pData->wWidth, pData->wHeight);
+
+               // Create image list if needed
+               if(m_hImageList == NULL)
+               {
+                       // Check if the bitmap is 32-bit (alpha channel) bitmap (valid for Windows XP only)
+                       T* pT = static_cast<T*>(this);
+                       m_bAlphaImages = AtlIsAlphaBitmapResource(image);
+
+                       if(!pT->CreateInternalImageList(pData->wItemCount))
+                               return FALSE;
+               }
+
+#if _WTL_CMDBAR_VISTA_MENUS
+               int nOldImageCount = ::ImageList_GetImageCount(m_hImageList);
+#endif // _WTL_CMDBAR_VISTA_MENUS
+
+               // Add bitmap to our image list
+               CBitmap bmp;
+               if(bMapped)
+               {
+                       ATLASSERT(HIWORD(PtrToUlong(image.m_lpstr)) == 0);   // if mapped, must be a numeric ID
+                       int nIDImage = (int)(short)LOWORD(PtrToUlong(image.m_lpstr));
+                       bmp.LoadMappedBitmap(nIDImage, (WORD)nFlags, lpColorMap, nMapSize);
+               }
+               else
+               {
+                       if(m_bAlphaImages)
+                               bmp = (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
+                       else
+                               bmp.LoadBitmap(image.m_lpstr);
+               }
+               ATLASSERT(bmp.m_hBitmap != NULL);
+               if(bmp.m_hBitmap == NULL)
+                       return FALSE;
+               if(::ImageList_AddMasked(m_hImageList, bmp, m_clrMask) == -1)
+                       return FALSE;
+
+               // Fill the array with command IDs
+               for(int i = 0; i < nItems; i++)
+               {
+                       if(pItems[i] != 0)
+                               m_arrCommand.Add(pItems[i]);
+               }
+
+               int nImageCount = ::ImageList_GetImageCount(m_hImageList);
+               ATLASSERT(nImageCount == m_arrCommand.GetSize());
+               if(nImageCount != m_arrCommand.GetSize())
+                       return FALSE;
+
+#if _WTL_CMDBAR_VISTA_MENUS
+               if(RunTimeHelper::IsVista())
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->_AddVistaBitmapsFromImageList(nOldImageCount, nImageCount - nOldImageCount);
+                       ATLASSERT(nImageCount == m_arrVistaBitmap.GetSize());
+               }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+
+               return TRUE;
+       }
+
+       BOOL AddBitmap(ATL::_U_STRINGorID bitmap, int nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               CBitmap bmp;
+               bmp.LoadBitmap(bitmap.m_lpstr);
+               if(bmp.m_hBitmap == NULL)
+                       return FALSE;
+               return AddBitmap(bmp, nCommandID);
+       }
+
+       BOOL AddBitmap(HBITMAP hBitmap, UINT nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               // Create image list if it doesn't exist
+               if(m_hImageList == NULL)
+               {
+                       if(!pT->CreateInternalImageList(1))
+                               return FALSE;
+               }
+               // check bitmap size
+               CBitmapHandle bmp = hBitmap;
+               SIZE size = { 0, 0 };
+               bmp.GetSize(size);
+               if(size.cx != m_szBitmap.cx || size.cy != m_szBitmap.cy)
+               {
+                       ATLASSERT(FALSE);   // must match size!
+                       return FALSE;
+               }
+               // add bitmap
+               int nRet = ::ImageList_AddMasked(m_hImageList, hBitmap, m_clrMask);
+               if(nRet == -1)
+                       return FALSE;
+               BOOL bRet = m_arrCommand.Add((WORD)nCommandID);
+               ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrCommand.GetSize());
+#if _WTL_CMDBAR_VISTA_MENUS
+               if(RunTimeHelper::IsVista())
+               {
+                       pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize() - 1);
+                       ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.GetSize());
+               }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+               return bRet;
+       }
+
+       BOOL AddIcon(ATL::_U_STRINGorID icon, UINT nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr);
+               if(hIcon == NULL)
+                       return FALSE;
+               return AddIcon(hIcon, nCommandID);
+       }
+
+       BOOL AddIcon(HICON hIcon, UINT nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               // create image list if it doesn't exist
+               if(m_hImageList == NULL)
+               {
+                       if(!pT->CreateInternalImageList(1))
+                               return FALSE;
+               }
+
+               int nRet = ::ImageList_AddIcon(m_hImageList, hIcon);
+               if(nRet == -1)
+                       return FALSE;
+               BOOL bRet = m_arrCommand.Add((WORD)nCommandID);
+               ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrCommand.GetSize());
+#if _WTL_CMDBAR_VISTA_MENUS
+               if(RunTimeHelper::IsVista())
+               {
+                       pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize() - 1);
+                       ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.GetSize());
+               }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+               return bRet;
+       }
+
+       BOOL ReplaceBitmap(ATL::_U_STRINGorID bitmap, int nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               CBitmap bmp;
+               bmp.LoadBitmap(bitmap.m_lpstr);
+               if(bmp.m_hBitmap == NULL)
+                       return FALSE;
+               return ReplaceBitmap(bmp, nCommandID);
+       }
+
+       BOOL ReplaceBitmap(HBITMAP hBitmap, UINT nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               BOOL bRet = FALSE;
+               for(int i = 0; i < m_arrCommand.GetSize(); i++)
+               {
+                       if(m_arrCommand[i] == nCommandID)
+                       {
+                               bRet = ::ImageList_Remove(m_hImageList, i);
+                               if(bRet)
+                               {
+                                       m_arrCommand.RemoveAt(i);
+#if _WTL_CMDBAR_VISTA_MENUS
+                                       if(RunTimeHelper::IsVista())
+                                       {
+                                               if(m_arrVistaBitmap[i] != NULL)
+                                                       ::DeleteObject(m_arrVistaBitmap[i]);
+                                               m_arrVistaBitmap.RemoveAt(i);
+                                       }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+                               }
+                               break;
+                       }
+               }
+               if(bRet)
+                       bRet = AddBitmap(hBitmap, nCommandID);
+               return bRet;
+       }
+
+       BOOL ReplaceIcon(ATL::_U_STRINGorID icon, UINT nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr);
+               if(hIcon == NULL)
+                       return FALSE;
+               return ReplaceIcon(hIcon, nCommandID);
+       }
+
+       BOOL ReplaceIcon(HICON hIcon, UINT nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               BOOL bRet = FALSE;
+               for(int i = 0; i < m_arrCommand.GetSize(); i++)
+               {
+                       if(m_arrCommand[i] == nCommandID)
+                       {
+                               bRet = (::ImageList_ReplaceIcon(m_hImageList, i, hIcon) != -1);
+#if _WTL_CMDBAR_VISTA_MENUS
+                               if(RunTimeHelper::IsVista() && bRet != FALSE)
+                               {
+                                       T* pT = static_cast<T*>(this);
+                                       pT->_ReplaceVistaBitmapFromImageList(i);
+                               }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+                               break;
+                       }
+               }
+               return bRet;
+       }
+
+       BOOL RemoveImage(int nCommandID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               BOOL bRet = FALSE;
+               for(int i = 0; i < m_arrCommand.GetSize(); i++)
+               {
+                       if(m_arrCommand[i] == nCommandID)
+                       {
+                               bRet = ::ImageList_Remove(m_hImageList, i);
+                               if(bRet)
+                               {
+                                       m_arrCommand.RemoveAt(i);
+#if _WTL_CMDBAR_VISTA_MENUS
+                                       if(RunTimeHelper::IsVista())
+                                       {
+                                               if(m_arrVistaBitmap[i] != NULL)
+                                                       ::DeleteObject(m_arrVistaBitmap[i]);
+                                               m_arrVistaBitmap.RemoveAt(i);
+                                       }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+                               }
+                               break;
+                       }
+               }
+               return bRet;
+       }
+
+       BOOL RemoveAllImages()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Removing all images\n"));
+               BOOL bRet = ::ImageList_RemoveAll(m_hImageList);
+               if(bRet)
+               {
+                       m_arrCommand.RemoveAll();
+#if _WTL_CMDBAR_VISTA_MENUS
+                       for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++)
+                       {
+                               if(m_arrVistaBitmap[i] != NULL)
+                                       ::DeleteObject(m_arrVistaBitmap[i]);
+                       }
+                       m_arrVistaBitmap.RemoveAll();
+#endif // _WTL_CMDBAR_VISTA_MENUS
+               }
+               return bRet;
+       }
+
+       BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(::IsMenu(hMenu));
+               if(!::IsMenu(hMenu))
+                       return FALSE;
+               m_bContextMenu = true;
+               if(m_bUseKeyboardCues)
+                       m_bShowKeyboardCues = m_bKeyboardInput;
+               T* pT = static_cast<T*>(this);
+               return pT->DoTrackPopupMenu(hMenu, uFlags, x, y, lpParams);
+       }
+
+       BOOL SetMDIClient(HWND /*hWndMDIClient*/)
+       {
+               // Use CMDICommandBarCtrl for MDI support
+               ATLASSERT(FALSE);
+               return FALSE;
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CCommandBarCtrlImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_INITMENU, OnInitMenu)
+               MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
+               MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
+               MESSAGE_HANDLER(GetAutoPopupMessage(), OnInternalAutoPopup)
+               MESSAGE_HANDLER(GetGetBarMessage(), OnInternalGetBar)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+               MESSAGE_HANDLER(WM_MENUCHAR, OnMenuChar)
+
+               MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
+               MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
+               MESSAGE_HANDLER(WM_CHAR, OnChar)
+               MESSAGE_HANDLER(WM_SYSKEYDOWN, OnSysKeyDown)
+               MESSAGE_HANDLER(WM_SYSKEYUP, OnSysKeyUp)
+               MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar)
+// public API handlers - these stay to support chevrons in atlframe.h
+               MESSAGE_HANDLER(CBRM_GETMENU, OnAPIGetMenu)
+               MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnAPITrackPopupMenu)
+               MESSAGE_HANDLER(CBRM_GETCMDBAR, OnAPIGetCmdBar)
+
+               MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
+               MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
+
+               MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg)
+       ALT_MSG_MAP(1)   // Parent window messages
+               NOTIFY_CODE_HANDLER(TBN_HOTITEMCHANGE, OnParentHotItemChange)
+               NOTIFY_CODE_HANDLER(TBN_DROPDOWN, OnParentDropDown)
+               MESSAGE_HANDLER(WM_INITMENUPOPUP, OnParentInitMenuPopup)
+               MESSAGE_HANDLER(GetGetBarMessage(), OnParentInternalGetBar)
+               MESSAGE_HANDLER(WM_SYSCOMMAND, OnParentSysCommand)
+               MESSAGE_HANDLER(CBRM_GETMENU, OnParentAPIGetMenu)
+               MESSAGE_HANDLER(WM_MENUCHAR, OnParentMenuChar)
+               MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnParentAPITrackPopupMenu)
+               MESSAGE_HANDLER(CBRM_GETCMDBAR, OnParentAPIGetCmdBar)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnParentSettingChange)
+
+               MESSAGE_HANDLER(WM_DRAWITEM, OnParentDrawItem)
+               MESSAGE_HANDLER(WM_MEASUREITEM, OnParentMeasureItem)
+
+               MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate)
+               NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnParentCustomDraw)
+       ALT_MSG_MAP(2)   // MDI client window messages
+               // Use CMDICommandBarCtrl for MDI support
+       ALT_MSG_MAP(3)   // Message hook messages
+               MESSAGE_HANDLER(WM_MOUSEMOVE, OnHookMouseMove)
+               MESSAGE_HANDLER(WM_SYSKEYDOWN, OnHookSysKeyDown)
+               MESSAGE_HANDLER(WM_SYSKEYUP, OnHookSysKeyUp)
+               MESSAGE_HANDLER(WM_SYSCHAR, OnHookSysChar)
+               MESSAGE_HANDLER(WM_KEYDOWN, OnHookKeyDown)
+               MESSAGE_HANDLER(WM_NEXTMENU, OnHookNextMenu)
+               MESSAGE_HANDLER(WM_CHAR, OnHookChar)
+       END_MSG_MAP()
+
+       LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LPMSG pMsg = (LPMSG)lParam;
+               if(pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
+                       m_bKeyboardInput = false;
+               else if(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
+                       m_bKeyboardInput = true;
+               LRESULT lRet = 0;
+               ProcessWindowMessage(pMsg->hwnd, pMsg->message, pMsg->wParam, pMsg->lParam, lRet, 3);
+               return lRet;
+       }
+
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               // Let the toolbar initialize itself
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               // get and use system settings
+               T* pT = static_cast<T*>(this);
+               pT->GetSystemSettings();
+               // Parent init
+               ATL::CWindow wndParent = GetParent();
+               ATL::CWindow wndTopLevelParent = wndParent.GetTopLevelParent();
+               m_wndParent.SubclassWindow(wndTopLevelParent);
+               // Toolbar Init
+               SetButtonStructSize();
+               SetImageList(NULL);
+
+               // Create message hook if needed
+               CWindowCreateCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::OnCreate.\n"));
+                       ATLASSERT(FALSE);
+                       return -1;
+               }
+
+               if(s_pmapMsgHook == NULL)
+               {
+                       ATLTRY(s_pmapMsgHook = new CMsgHookMap);
+                       ATLASSERT(s_pmapMsgHook != NULL);
+               }
+
+               if(s_pmapMsgHook != NULL)
+               {
+                       DWORD dwThreadID = ::GetCurrentThreadId();
+                       _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID);
+                       if(pData == NULL)
+                       {
+                               ATLTRY(pData = new _MsgHookData);
+                               ATLASSERT(pData != NULL);
+                               HHOOK hMsgHook = ::SetWindowsHookEx(WH_GETMESSAGE, MessageHookProc, ModuleHelper::GetModuleInstance(), dwThreadID);
+                               ATLASSERT(hMsgHook != NULL);
+                               if(pData != NULL && hMsgHook != NULL)
+                               {
+                                       pData->hMsgHook = hMsgHook;
+                                       pData->dwUsage = 1;
+                                       BOOL bRet = s_pmapMsgHook->Add(dwThreadID, pData);
+                                       bRet;
+                                       ATLASSERT(bRet);
+                               }
+                       }
+                       else
+                       {
+                               (pData->dwUsage)++;
+                       }
+               }
+               lock.Unlock();
+
+               // Get layout
+#if (WINVER >= 0x0500)
+               m_bLayoutRTL = ((GetExStyle() & WS_EX_LAYOUTRTL) != 0);
+#endif // (WINVER >= 0x0500)
+
+               return lRet;
+       }
+
+       LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+#if _WTL_CMDBAR_VISTA_MENUS
+               if(m_bVistaMenus && (m_hMenu != NULL))
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->_RemoveVistaBitmapsFromMenu();
+               }
+
+               for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++)
+               {
+                       if(m_arrVistaBitmap[i] != NULL)
+                               ::DeleteObject(m_arrVistaBitmap[i]);
+               }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+
+               if(m_bAttachedMenu)   // nothing to do in this mode
+                       return lRet;
+
+               CWindowCreateCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::OnDestroy.\n"));
+                       ATLASSERT(FALSE);
+                       return lRet;
+               }
+
+               if(s_pmapMsgHook != NULL)
+               {
+                       DWORD dwThreadID = ::GetCurrentThreadId();
+                       _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID);
+                       if(pData != NULL)
+                       {
+                               (pData->dwUsage)--;
+                               if(pData->dwUsage == 0)
+                               {
+                                       BOOL bRet = ::UnhookWindowsHookEx(pData->hMsgHook);
+                                       ATLASSERT(bRet);
+                                       bRet = s_pmapMsgHook->Remove(dwThreadID);
+                                       ATLASSERT(bRet);
+                                       if(bRet)
+                                               delete pData;
+                               }
+
+                               if(s_pmapMsgHook->GetSize() == 0)
+                               {
+                                       delete s_pmapMsgHook;
+                                       s_pmapMsgHook = NULL;
+                               }
+                       }
+               }
+
+               lock.Unlock();
+
+               return lRet;
+       }
+
+       LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyDown\n"));
+#endif
+               bHandled = FALSE;
+               // Simulate Alt+Space for the parent
+               if(wParam == VK_SPACE)
+               {
+                       m_wndParent.PostMessage(WM_SYSKEYDOWN, wParam, lParam | (1 << 29));
+                       bHandled = TRUE;
+               }
+#if (_WIN32_IE >= 0x0500)
+               else if(wParam == VK_LEFT || wParam == VK_RIGHT)
+               {
+                       WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT;
+
+                       if(!m_bMenuActive)
+                       {
+                               T* pT = static_cast<T*>(this);
+                               int nBtn = GetHotItem();
+                               int nNextBtn = (wParam == wpNext) ? pT->GetNextMenuItem(nBtn) : pT->GetPreviousMenuItem(nBtn);
+                               if(nNextBtn == -2)
+                               {
+                                       SetHotItem(-1);
+                                       if(pT->DisplayChevronMenu())
+                                               bHandled = TRUE;
+                               }
+                       }
+               }
+#endif // (_WIN32_IE >= 0x0500)
+               return 0;
+       }
+
+       LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyUp\n"));
+#endif
+               if(wParam != VK_SPACE)
+                       bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnChar\n"));
+#endif
+               if(wParam != VK_SPACE)
+                       bHandled = FALSE;
+               else
+                       return 0;
+               // Security
+               if(!m_wndParent.IsWindowEnabled() || ::GetFocus() != m_hWnd)
+                       return 0;
+
+               // Handle mnemonic press when we have focus
+               int nBtn = 0;
+               if(wParam != VK_RETURN && !MapAccelerator((TCHAR)LOWORD(wParam), nBtn))
+               {
+#if (_WIN32_IE >= 0x0500)
+                       if((TCHAR)LOWORD(wParam) != _chChevronShortcut)
+#endif // (_WIN32_IE >= 0x0500)
+                               ::MessageBeep(0);
+               }
+               else
+               {
+#if (_WIN32_IE >= 0x0500)
+                       RECT rcClient = { 0 };
+                       GetClientRect(&rcClient);
+                       RECT rcBtn = { 0 };
+                       GetItemRect(nBtn, &rcBtn);
+                       TBBUTTON tbb = { 0 };
+                       GetButton(nBtn, &tbb);
+                       if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right)
+                       {
+#endif // (_WIN32_IE >= 0x0500)
+                               PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+                               if(wParam != VK_RETURN)
+                                       SetHotItem(nBtn);
+#if (_WIN32_IE >= 0x0500)
+                       }
+                       else
+                       {
+                               ::MessageBeep(0);
+                               bHandled = TRUE;
+                       }
+#endif // (_WIN32_IE >= 0x0500)
+               }
+               return 0;
+       }
+
+       LRESULT OnSysKeyDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyDown\n"));
+#endif
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnSysKeyUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyUp\n"));
+#endif
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnSysChar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysChar\n"));
+#endif
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_bAttachedMenu || (m_dwExtendedStyle & CBR_EX_TRANSPARENT))
+               {
+                       bHandled = FALSE;
+                       return 0;
+               }
+
+               CDCHandle dc = (HDC)wParam;
+               RECT rect = { 0 };
+               GetClientRect(&rect);
+               dc.FillRect(&rect, COLOR_MENU);
+
+               return 1;   // don't do the default erase
+       }
+
+       LRESULT OnInitMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               int nIndex = GetHotItem();
+               SendMessage(WM_MENUSELECT, MAKEWPARAM(nIndex, MF_POPUP|MF_HILITE), (LPARAM)m_hMenu);
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if((BOOL)HIWORD(lParam))   // System menu, do nothing
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               if(!(m_bAttachedMenu || m_bMenuActive))   // Not attached or ours, do nothing
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnInitMenuPopup\n"));
+#endif
+               // forward to the parent or subclassed window, so it can handle update UI
+               LRESULT lRet = 0;
+               if(m_bAttachedMenu)
+                       lRet = DefWindowProc(uMsg, wParam, (lParam || m_bContextMenu) ? lParam : GetHotItem());
+               else
+                       lRet = m_wndParent.DefWindowProc(uMsg, wParam, (lParam || m_bContextMenu) ? lParam : GetHotItem());
+
+#if _WTL_CMDBAR_VISTA_MENUS
+               // If Vista menus are active, just set bitmaps and return
+               if(m_bVistaMenus)
+               {
+                       CMenuHandle menu = (HMENU)wParam;
+                       ATLASSERT(menu.m_hMenu != NULL);
+
+                       for(int i = 0; i < menu.GetMenuItemCount(); i++)
+                       {
+                               WORD nID = (WORD)menu.GetMenuItemID(i);
+                               int nIndex = m_arrCommand.Find(nID);
+
+                               CMenuItemInfo mii;
+                               mii.fMask = MIIM_BITMAP;
+                               mii.hbmpItem = (m_bImagesVisible && (nIndex != -1)) ? m_arrVistaBitmap[nIndex] : NULL;
+                               menu.SetMenuItemInfo(i, TRUE, &mii);
+                       }
+
+                       return lRet;
+               }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+
+               // Convert menu items to ownerdraw, add our data
+               if(m_bImagesVisible)
+               {
+                       CMenuHandle menuPopup = (HMENU)wParam;
+                       ATLASSERT(menuPopup.m_hMenu != NULL);
+
+                       T* pT = static_cast<T*>(this);
+                       pT;   // avoid level 4 warning
+                       TCHAR szString[pT->_nMaxMenuItemTextLength];
+                       BOOL bRet = FALSE;
+                       for(int i = 0; i < menuPopup.GetMenuItemCount(); i++)
+                       {
+                               CMenuItemInfo mii;
+                               mii.cch = pT->_nMaxMenuItemTextLength;
+                               mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
+                               mii.dwTypeData = szString;
+                               bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii);
+                               ATLASSERT(bRet);
+
+                               if(!(mii.fType & MFT_OWNERDRAW))   // Not already an ownerdraw item
+                               {
+                                       mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
+                                       _MenuItemData* pMI = NULL;
+                                       ATLTRY(pMI = new _MenuItemData);
+                                       ATLASSERT(pMI != NULL);
+                                       if(pMI != NULL)
+                                       {
+                                               pMI->fType = mii.fType;
+                                               pMI->fState = mii.fState;
+                                               mii.fType |= MFT_OWNERDRAW;
+                                               pMI->iButton = -1;
+                                               for(int j = 0; j < m_arrCommand.GetSize(); j++)
+                                               {
+                                                       if(m_arrCommand[j] == mii.wID)
+                                                       {
+                                                               pMI->iButton = j;
+                                                               break;
+                                                       }
+                                               }
+                                               int cchLen = lstrlen(szString) + 1;
+                                               pMI->lpstrText = NULL;
+                                               ATLTRY(pMI->lpstrText = new TCHAR[cchLen]);
+                                               ATLASSERT(pMI->lpstrText != NULL);
+                                               if(pMI->lpstrText != NULL)
+                                                       SecureHelper::strcpy_x(pMI->lpstrText, cchLen, szString);
+                                               mii.dwItemData = (ULONG_PTR)pMI;
+                                               bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii);
+                                               ATLASSERT(bRet);
+                                       }
+                               }
+                       }
+
+                       // Add it to the list
+                       m_stackMenuHandle.Push(menuPopup.m_hMenu);
+               }
+
+               return lRet;
+       }
+
+       LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if(!m_bAttachedMenu)   // Not attached, do nothing, forward to parent
+               {
+                       m_bPopupItem = (lParam != NULL) && ((HMENU)lParam != m_hMenu) && (HIWORD(wParam) & MF_POPUP);
+                       if(m_wndParent.IsWindow())
+                               m_wndParent.SendMessage(uMsg, wParam, lParam);
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               // Check if a menu is closing, do a cleanup
+               if(HIWORD(wParam) == 0xFFFF && lParam == NULL)   // Menu closing
+               {
+#ifdef _CMDBAR_EXTRA_TRACE
+                       ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuSelect - CLOSING!!!!\n"));
+#endif
+                       ATLASSERT(m_stackMenuWnd.GetSize() == 0);
+                       // Restore the menu items to the previous state for all menus that were converted
+                       if(m_bImagesVisible)
+                       {
+                               HMENU hMenu = NULL;
+                               while((hMenu = m_stackMenuHandle.Pop()) != NULL)
+                               {
+                                       CMenuHandle menuPopup = hMenu;
+                                       ATLASSERT(menuPopup.m_hMenu != NULL);
+                                       // Restore state and delete menu item data
+                                       BOOL bRet = FALSE;
+                                       for(int i = 0; i < menuPopup.GetMenuItemCount(); i++)
+                                       {
+                                               CMenuItemInfo mii;
+                                               mii.fMask = MIIM_DATA | MIIM_TYPE;
+                                               bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii);
+                                               ATLASSERT(bRet);
+
+                                               _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData;
+                                               if(pMI != NULL && pMI->IsCmdBarMenuItem())
+                                               {
+                                                       mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
+                                                       mii.fType = pMI->fType;
+                                                       mii.dwTypeData = pMI->lpstrText;
+                                                       mii.cch = lstrlen(pMI->lpstrText);
+                                                       mii.dwItemData = NULL;
+
+                                                       bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii);
+                                                       ATLASSERT(bRet);
+
+                                                       delete [] pMI->lpstrText;
+                                                       pMI->dwMagic = 0x6666;
+                                                       delete pMI;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnInternalAutoPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               int nIndex = (int)wParam;
+               T* pT = static_cast<T*>(this);
+               pT->DoPopupMenu(nIndex, false);
+               return 0;
+       }
+
+       LRESULT OnInternalGetBar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // Let's make sure we're not embedded in another process
+               if((LPVOID)wParam != NULL)
+                       *((DWORD*)wParam) = GetCurrentProcessId();
+               if(IsWindowVisible())
+                       return (LRESULT)static_cast<CCommandBarCtrlBase*>(this);
+               else
+                       return NULL;
+       }
+
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+#ifndef SPI_GETKEYBOARDCUES
+               const UINT SPI_SETKEYBOARDCUES = 0x100B;
+#endif // !SPI_GETKEYBOARDCUES
+#ifndef SPI_GETFLATMENU
+               const UINT SPI_SETFLATMENU = 0x1023;
+#endif // !SPI_GETFLATMENU
+
+               if(wParam == SPI_SETNONCLIENTMETRICS || wParam == SPI_SETKEYBOARDCUES || wParam == SPI_SETFLATMENU)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->GetSystemSettings();
+               }
+
+               return 0;
+       }
+
+       LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+               LPWINDOWPOS lpWP = (LPWINDOWPOS)lParam;
+               int cyMin = ::GetSystemMetrics(SM_CYMENU);
+               if(lpWP->cy < cyMin)
+               lpWP->cy = cyMin;
+
+               return lRet;
+       }
+
+       LRESULT OnMenuChar(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuChar\n"));
+#endif
+               bHandled = TRUE;
+               T* pT = static_cast<T*>(this);
+
+               LRESULT lRet;
+               if(m_bMenuActive && LOWORD(wParam) != 0x0D)
+                       lRet = 0;
+               else
+                       lRet = MAKELRESULT(1, 1);
+
+               if(m_bMenuActive && HIWORD(wParam) == MF_POPUP)
+               {
+                       // Convert character to lower/uppercase and possibly Unicode, using current keyboard layout
+                       TCHAR ch = (TCHAR)LOWORD(wParam);
+                       CMenuHandle menu = (HMENU)lParam;
+                       int nCount = ::GetMenuItemCount(menu);
+                       int nRetCode = MNC_EXECUTE;
+                       BOOL bRet = FALSE;
+                       TCHAR szString[pT->_nMaxMenuItemTextLength];
+                       WORD wMnem = 0;
+                       bool bFound = false;
+                       for(int i = 0; i < nCount; i++)
+                       {
+                               CMenuItemInfo mii;
+                               mii.cch = pT->_nMaxMenuItemTextLength;
+                               mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
+                               mii.dwTypeData = szString;
+                               bRet = menu.GetMenuItemInfo(i, TRUE, &mii);
+                               if(!bRet || (mii.fType & MFT_SEPARATOR))
+                                       continue;
+                               _MenuItemData* pmd = (_MenuItemData*)mii.dwItemData;
+                               if(pmd != NULL && pmd->IsCmdBarMenuItem())
+                               {
+                                       LPTSTR p = pmd->lpstrText;
+
+                                       if(p != NULL)
+                                       {
+                                               while(*p && *p != _T('&'))
+                                                       p = ::CharNext(p);
+                                               if(p != NULL && *p)
+                                               {
+                                                       DWORD dwP = MAKELONG(*(++p), 0);
+                                                       DWORD dwC = MAKELONG(ch, 0);
+                                                       if(::CharLower((LPTSTR)ULongToPtr(dwP)) == ::CharLower((LPTSTR)ULongToPtr(dwC)))
+                                                       {
+                                                               if(!bFound)
+                                                               {
+                                                                       wMnem = (WORD)i;
+                                                                       bFound = true;
+                                                               }
+                                                               else
+                                                               {
+                                                                       nRetCode = MNC_SELECT;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       if(bFound)
+                       {
+                               if(nRetCode == MNC_EXECUTE)
+                               {
+                                       PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
+                                       pT->GiveFocusBack();
+                               }
+                               bHandled = TRUE;
+                               lRet = MAKELRESULT(wMnem, nRetCode);
+                       }
+               } 
+               else if(!m_bMenuActive)
+               {
+                       int nBtn = 0;
+                       if(!MapAccelerator((TCHAR)LOWORD(wParam), nBtn))
+                       {
+                               bHandled = FALSE;
+                               PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
+                               pT->GiveFocusBack();
+
+#if (_WIN32_IE >= 0x0500)
+                               // check if we should display chevron menu
+                               if((TCHAR)LOWORD(wParam) == pT->_chChevronShortcut)
+                               {
+                                       if(pT->DisplayChevronMenu())
+                                               bHandled = TRUE;
+                               }
+#endif // (_WIN32_IE >= 0x0500)
+                       }
+                       else if(m_wndParent.IsWindowEnabled())
+                       {
+#if (_WIN32_IE >= 0x0500)
+                               RECT rcClient = { 0 };
+                               GetClientRect(&rcClient);
+                               RECT rcBtn = { 0 };
+                               GetItemRect(nBtn, &rcBtn);
+                               TBBUTTON tbb = { 0 };
+                               GetButton(nBtn, &tbb);
+                               if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right)
+                               {
+#endif // (_WIN32_IE >= 0x0500)
+                                       if(m_bUseKeyboardCues && !m_bShowKeyboardCues)
+                                       {
+                                               m_bAllowKeyboardCues = true;
+                                               ShowKeyboardCues(true);
+                                       }
+                                       pT->TakeFocus();
+                                       PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+                                       SetHotItem(nBtn);
+#if (_WIN32_IE >= 0x0500)
+                               }
+                               else
+                               {
+                                       ::MessageBeep(0);
+                               }
+#endif // (_WIN32_IE >= 0x0500)
+                       }
+               }
+
+               return lRet;
+       }
+
+       LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               LPDRAWITEMSTRUCT lpDrawItemStruct = (LPDRAWITEMSTRUCT)lParam;
+               _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData;
+               if(lpDrawItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->IsCmdBarMenuItem())
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->DrawItem(lpDrawItemStruct);
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+               return (LRESULT)TRUE;
+       }
+
+       LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               LPMEASUREITEMSTRUCT lpMeasureItemStruct = (LPMEASUREITEMSTRUCT)lParam;
+               _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData;
+               if(lpMeasureItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->IsCmdBarMenuItem())
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->MeasureItem(lpMeasureItemStruct);
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+               return (LRESULT)TRUE;
+       }
+
+// API message handlers
+       LRESULT OnAPIGetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return (LRESULT)m_hMenu;
+       }
+
+       LRESULT OnAPITrackPopupMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               if(lParam == NULL)
+                       return FALSE;
+               LPCBRPOPUPMENU lpCBRPopupMenu = (LPCBRPOPUPMENU)lParam;
+               if(lpCBRPopupMenu->cbSize != sizeof(CBRPOPUPMENU))
+                       return FALSE;
+
+               T* pT = static_cast<T*>(this);
+               return pT->TrackPopupMenu(lpCBRPopupMenu->hMenu, lpCBRPopupMenu->uFlags, lpCBRPopupMenu->x, lpCBRPopupMenu->y, lpCBRPopupMenu->lptpm);
+       }
+
+       LRESULT OnAPIGetCmdBar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return (LRESULT)m_hWnd;
+       }
+
+// Parent window message handlers
+       LRESULT OnParentHotItemChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               LPNMTBHOTITEM lpNMHT = (LPNMTBHOTITEM)pnmh;
+
+               // Check if this comes from us
+               if(pnmh->hwndFrom != m_hWnd)
+               {
+                       bHandled = FALSE;
+                       return 0;
+               }
+
+               bool bBlockTracking = false;
+               if((m_dwExtendedStyle & CBR_EX_TRACKALWAYS) == 0)
+               {
+                       DWORD dwProcessID;
+                       ::GetWindowThreadProcessId(::GetActiveWindow(), &dwProcessID);
+                       bBlockTracking = (::GetCurrentProcessId() != dwProcessID);
+               }
+
+               if((!m_wndParent.IsWindowEnabled() || bBlockTracking) && (lpNMHT->dwFlags & HICF_MOUSE))
+               {
+                       return 1;
+               }
+               else
+               {
+#ifndef HICF_LMOUSE
+                       const DWORD HICF_LMOUSE = 0x00000080;   // left mouse button selected
+#endif
+                       bHandled = FALSE;
+
+                       // Send WM_MENUSELECT to the app if it needs to display a status text
+                       if(!(lpNMHT->dwFlags & HICF_MOUSE)
+                               && !(lpNMHT->dwFlags & HICF_ACCELERATOR)
+                               && !(lpNMHT->dwFlags & HICF_LMOUSE))
+                       {
+                               if(lpNMHT->dwFlags & HICF_ENTERING)
+                                       m_wndParent.SendMessage(WM_MENUSELECT, 0, (LPARAM)m_hMenu);
+                               if(lpNMHT->dwFlags & HICF_LEAVING)
+                                       m_wndParent.SendMessage(WM_MENUSELECT, MAKEWPARAM(0, 0xFFFF), NULL);
+                       }
+
+                       return 0;
+               }
+       }
+
+       LRESULT OnParentDropDown(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               // Check if this comes from us
+               if(pnmh->hwndFrom != m_hWnd)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               T* pT = static_cast<T*>(this);
+               if(::GetFocus() != m_hWnd)
+                       pT->TakeFocus();
+               LPNMTOOLBAR pNMToolBar = (LPNMTOOLBAR)pnmh;
+               int nIndex = CommandToIndex(pNMToolBar->iItem);
+               m_bContextMenu = false;
+               m_bEscapePressed = false;
+               pT->DoPopupMenu(nIndex, true);
+
+               return TBDDRET_DEFAULT;
+       }
+
+       LRESULT OnParentInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               return OnInitMenuPopup(uMsg, wParam, lParam, bHandled);
+       }
+
+       LRESULT OnParentInternalGetBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               return OnInternalGetBar(uMsg, wParam, lParam, bHandled);
+       }
+
+       LRESULT OnParentSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               bHandled = FALSE;
+               if((m_uSysKey == VK_MENU 
+                       || (m_uSysKey == VK_F10 && !(::GetKeyState(VK_SHIFT) & 0x80))
+                       || m_uSysKey == VK_SPACE) 
+                       && wParam == SC_KEYMENU)
+               {
+                       T* pT = static_cast<T*>(this);
+                       if(::GetFocus() == m_hWnd)
+                       {
+                               pT->GiveFocusBack();   // exit menu "loop"
+                               PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
+                       }
+                       else if(m_uSysKey != VK_SPACE && !m_bSkipMsg)
+                       {
+                               if(m_bUseKeyboardCues && !m_bShowKeyboardCues && m_bAllowKeyboardCues)
+                                       ShowKeyboardCues(true);
+
+                               pT->TakeFocus();      // enter menu "loop"
+                               bHandled = TRUE;
+                       }
+                       else if(m_uSysKey != VK_SPACE)
+                       {
+                               bHandled = TRUE;
+                       }
+               }
+               m_bSkipMsg = false;
+               return 0;
+       }
+
+       LRESULT OnParentAPIGetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               return OnAPIGetMenu(uMsg, wParam, lParam, bHandled);
+       }
+
+       LRESULT OnParentMenuChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               return OnMenuChar(uMsg, wParam, lParam, bHandled);
+       }
+
+       LRESULT OnParentAPITrackPopupMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               return OnAPITrackPopupMenu(uMsg, wParam, lParam, bHandled);
+       }
+
+       LRESULT OnParentAPIGetCmdBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               return OnAPIGetCmdBar(uMsg, wParam, lParam, bHandled);
+       }
+
+       LRESULT OnParentSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               OnSettingChange(uMsg, wParam, lParam, bHandled);
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnParentDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               return OnDrawItem(uMsg, wParam, lParam, bHandled);
+       }
+
+       LRESULT OnParentMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               return OnMeasureItem(uMsg, wParam, lParam, bHandled);
+       }
+
+       LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               m_bParentActive = (LOWORD(wParam) != WA_INACTIVE);
+               if(!m_bParentActive && m_bUseKeyboardCues && m_bShowKeyboardCues)
+               {
+                       ShowKeyboardCues(false);   // this will repaint our window
+               }
+               else
+               {
+                       Invalidate();
+                       UpdateWindow();
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnParentCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               LRESULT lRet = CDRF_DODEFAULT;
+               bHandled = FALSE;
+               if(pnmh->hwndFrom == m_hWnd)
+               {
+                       LPNMTBCUSTOMDRAW lpTBCustomDraw = (LPNMTBCUSTOMDRAW)pnmh;
+                       if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
+                       {
+                               lRet = CDRF_NOTIFYITEMDRAW;
+                               bHandled = TRUE;
+                       }
+                       else if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
+                       {
+                               if(m_bFlatMenus)
+                               {
+#ifndef COLOR_MENUHILIGHT
+                                       const int COLOR_MENUHILIGHT = 29;
+#endif // !COLOR_MENUHILIGHT
+                                       bool bDisabled = ((lpTBCustomDraw->nmcd.uItemState & CDIS_DISABLED) == CDIS_DISABLED);
+                                       if(!bDisabled && ((lpTBCustomDraw->nmcd.uItemState & CDIS_HOT) == CDIS_HOT || 
+                                               (lpTBCustomDraw->nmcd.uItemState & CDIS_SELECTED) == CDIS_SELECTED))
+                                       {
+                                               ::FillRect(lpTBCustomDraw->nmcd.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_MENUHILIGHT));
+                                               ::FrameRect(lpTBCustomDraw->nmcd.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_HIGHLIGHT));
+                                               lpTBCustomDraw->clrText = ::GetSysColor(m_bParentActive ? COLOR_HIGHLIGHTTEXT : COLOR_GRAYTEXT);
+                                       }
+                                       else if(bDisabled || !m_bParentActive)
+                                       {
+                                               lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT);
+                                       }
+                                       CDCHandle dc = lpTBCustomDraw->nmcd.hdc;
+                                       dc.SetTextColor(lpTBCustomDraw->clrText);
+                                       dc.SetBkMode(lpTBCustomDraw->nStringBkMode);
+                                       HFONT hFont = GetFont();
+                                       HFONT hFontOld = NULL;
+                                       if(hFont != NULL)
+                                               hFontOld = dc.SelectFont(hFont);
+                                       const int cchText = 200;
+                                       TCHAR szText[cchText] = { 0 };
+                                       TBBUTTONINFO tbbi = { 0 };
+                                       tbbi.cbSize = sizeof(TBBUTTONINFO);
+                                       tbbi.dwMask = TBIF_TEXT;
+                                       tbbi.pszText = szText;
+                                       tbbi.cchText = cchText;
+                                       GetButtonInfo((int)lpTBCustomDraw->nmcd.dwItemSpec, &tbbi);
+                                       dc.DrawText(szText, -1, &lpTBCustomDraw->nmcd.rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX));
+                                       if(hFont != NULL)
+                                               dc.SelectFont(hFontOld);
+                                       lRet = CDRF_SKIPDEFAULT;
+                                       bHandled = TRUE;
+                               }
+                               else if(!m_bParentActive)
+                               {
+                                       lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT);
+                                       bHandled = TRUE;
+                               }
+                       }
+               }
+               return lRet;
+       }
+
+// Message hook handlers
+       LRESULT OnHookMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               static POINT s_point = { -1, -1 };
+               DWORD dwPoint = ::GetMessagePos();
+               POINT point = { GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint) };
+
+               bHandled = FALSE;
+               if(m_bMenuActive)
+               {
+                       if(::WindowFromPoint(point) == m_hWnd)
+                       {
+                               ScreenToClient(&point);
+                               int nHit = HitTest(&point);
+
+                               if((point.x != s_point.x || point.y != s_point.y) && nHit >= 0 && nHit < ::GetMenuItemCount(m_hMenu) && nHit != m_nPopBtn && m_nPopBtn != -1)
+                               {
+                                       TBBUTTON tbb = { 0 };
+                                       GetButton(nHit, &tbb);
+                                       if((tbb.fsState & TBSTATE_ENABLED) != 0)
+                                       {
+                                               m_nNextPopBtn = nHit | 0xFFFF0000;
+                                               HWND hWndMenu = m_stackMenuWnd.GetCurrent();
+                                               ATLASSERT(hWndMenu != NULL);
+
+                                               // this one is needed to close a menu if mouse button was down
+                                               ::PostMessage(hWndMenu, WM_LBUTTONUP, 0, MAKELPARAM(point.x, point.y));
+                                               // this one closes a popup menu
+                                               ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L);
+
+                                               bHandled = TRUE;
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       ScreenToClient(&point);
+               }
+
+               s_point = point;
+               return 0;
+       }
+
+       LRESULT OnHookSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               bHandled = FALSE;
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYDOWN (0x%2.2X)\n"), wParam);
+#endif
+
+               if(wParam == VK_MENU && m_bParentActive && m_bUseKeyboardCues && !m_bShowKeyboardCues && m_bAllowKeyboardCues)
+                       ShowKeyboardCues(true);
+
+               if(wParam != VK_SPACE && !m_bMenuActive && ::GetFocus() == m_hWnd)
+               {
+                       m_bAllowKeyboardCues = false;
+                       PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
+                       T* pT = static_cast<T*>(this);
+                       pT->GiveFocusBack();
+                       m_bSkipMsg = true;
+               }
+               else
+               {
+                       if(wParam == VK_SPACE && m_bUseKeyboardCues && m_bShowKeyboardCues)
+                       {
+                               m_bAllowKeyboardCues = true;
+                               ShowKeyboardCues(false);
+                       }
+                       m_uSysKey = (UINT)wParam;
+               }
+               return 0;
+       }
+
+       LRESULT OnHookSysKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(!m_bAllowKeyboardCues)
+                       m_bAllowKeyboardCues = true;
+               bHandled = FALSE;
+               wParam;
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYUP (0x%2.2X)\n"), wParam);
+#endif
+               return 0;
+       }
+
+       LRESULT OnHookSysChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               bHandled = FALSE;
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSCHAR (0x%2.2X)\n"), wParam);
+#endif
+
+               if(!m_bMenuActive && m_hWndHook != m_hWnd && wParam != VK_SPACE)
+                       bHandled = TRUE;
+               return 0;
+       }
+
+       LRESULT OnHookKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_KEYDOWN (0x%2.2X)\n"), wParam);
+#endif
+               bHandled = FALSE;
+               T* pT = static_cast<T*>(this);
+
+               if(wParam == VK_ESCAPE && m_stackMenuWnd.GetSize() <= 1)
+               {
+                       if(m_bMenuActive && !m_bContextMenu)
+                       {
+                               int nHot = GetHotItem();
+                               if(nHot == -1)
+                                       nHot = m_nPopBtn;
+                               if(nHot == -1)
+                                       nHot = 0;
+                               SetHotItem(nHot);
+                               bHandled = TRUE;
+                               pT->TakeFocus();
+                               m_bEscapePressed = true; // To keep focus
+                               m_bSkipPostDown = false;
+                       }
+                       else if(::GetFocus() == m_hWnd && m_wndParent.IsWindow())
+                       {
+                               SetHotItem(-1);
+                               pT->GiveFocusBack();
+                               bHandled = TRUE;
+                       }
+               }
+               else if(wParam == VK_RETURN || wParam == VK_UP || wParam == VK_DOWN)
+               {
+                       if(!m_bMenuActive && ::GetFocus() == m_hWnd && m_wndParent.IsWindow())
+                       {
+                               int nHot = GetHotItem();
+                               if(nHot != -1)
+                               {
+                                       if(wParam != VK_RETURN)
+                                       {
+                                               if(!m_bSkipPostDown)
+                                               {
+// IE4 only: WM_KEYDOWN doesn't generate TBN_DROPDOWN, we need to simulate a mouse click
+#if (_WIN32_IE < 0x0500)
+                                                       DWORD dwMajor = 0, dwMinor = 0;
+                                                       ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
+                                                       if(dwMajor <= 4 || (dwMajor == 5 && dwMinor < 80))
+                                                       {
+                                                               RECT rect;
+                                                               GetItemRect(nHot, &rect);
+                                                               PostMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(rect.left, rect.top));
+                                                       }
+#endif // (_WIN32_IE < 0x0500)
+                                                       PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+                                                       m_bSkipPostDown = true;
+                                               }
+                                               else
+                                               {
+                                                       ATLTRACE2(atlTraceUI, 0, _T("CmdBar - skipping posting another VK_DOWN\n"));
+                                                       m_bSkipPostDown = false;
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Can't find hot button\n"));
+                               }
+                       }
+                       if(wParam == VK_RETURN && m_bMenuActive)
+                       {
+                               PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
+                               m_nNextPopBtn = -1;
+                               pT->GiveFocusBack();
+                       }
+               }
+               else if(wParam == VK_LEFT || wParam == VK_RIGHT)
+               {
+                       WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT;
+                       WPARAM wpPrev = m_bLayoutRTL ? VK_RIGHT : VK_LEFT;
+
+                       if(m_bMenuActive && !m_bContextMenu && !(wParam == wpNext && m_bPopupItem))
+                       {
+                               bool bAction = false;
+                               if(wParam == wpPrev && s_pCurrentBar->m_stackMenuWnd.GetSize() == 1)
+                               {
+                                       m_nNextPopBtn = pT->GetPreviousMenuItem(m_nPopBtn);
+                                       if(m_nNextPopBtn != -1)
+                                               bAction = true;
+                               }
+                               else if(wParam == wpNext)
+                               {
+                                       m_nNextPopBtn = pT->GetNextMenuItem(m_nPopBtn);
+                                       if(m_nNextPopBtn != -1)
+                                               bAction = true;
+                               }
+                               HWND hWndMenu = m_stackMenuWnd.GetCurrent();
+                               ATLASSERT(hWndMenu != NULL);
+
+                               // Close the popup menu
+                               if(bAction)
+                               {
+                                       ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L);
+                                       if(wParam == wpNext)
+                                       {
+                                               int cItem = m_stackMenuWnd.GetSize() - 1;
+                                               while(cItem >= 0)
+                                               {
+                                                       hWndMenu = m_stackMenuWnd[cItem];
+                                                       if(hWndMenu != NULL)
+                                                               ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L);
+                                                       cItem--;
+                                               }
+                                       }
+#if (_WIN32_IE >= 0x0500)
+                                       if(m_nNextPopBtn == -2)
+                                       {
+                                               m_nNextPopBtn = -1;
+                                               pT->DisplayChevronMenu();
+                                       }
+#endif // (_WIN32_IE >= 0x0500)
+                                       bHandled = TRUE;
+                               }
+                       }
+               }
+               return 0;
+       }
+
+       LRESULT OnHookNextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_NEXTMENU\n"));
+#endif
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnHookChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_CHAR (0x%2.2X)\n"), wParam);
+#endif
+               bHandled = (wParam == VK_ESCAPE);
+               return 0;
+       }
+
+// Implementation - ownerdraw overrideables and helpers
+       void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
+       {
+               T* pT = static_cast<T*>(this);
+               if(m_bFlatMenus)
+                       pT->DrawItemFlat(lpDrawItemStruct);
+               else
+                       pT->DrawItem3D(lpDrawItemStruct);
+
+       }
+
+       void DrawItem3D(LPDRAWITEMSTRUCT lpDrawItemStruct)
+       {
+               _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData;
+               CDCHandle dc = lpDrawItemStruct->hDC;
+               const RECT& rcItem = lpDrawItemStruct->rcItem;
+               T* pT = static_cast<T*>(this);
+
+               if(pmd->fType & MFT_SEPARATOR)
+               {
+                       // draw separator
+                       RECT rc = rcItem;
+                       rc.top += (rc.bottom - rc.top) / 2;      // vertical center
+                       dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP);   // draw separator line
+               }
+               else            // not a separator
+               {
+                       BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED;
+                       BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
+                       BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED;
+                       BOOL bHasImage = FALSE;
+
+                       if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1)
+                               bSelected = FALSE;
+                       RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy };   // button rect
+                       ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2);          // center vertically
+
+                       int iButton = pmd->iButton;
+                       if(iButton >= 0)
+                       {
+                               bHasImage = TRUE;
+
+                               // calc drawing point
+                               SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy };
+                               sz.cx /= 2;
+                               sz.cy /= 2;
+                               POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy };
+
+                               // fill background depending on state
+                               if(!bChecked || (bSelected && !bDisabled))
+                               {
+                                       if(!bDisabled)
+                                               dc.FillRect(&rcButn, (bChecked && !bSelected) ? COLOR_3DLIGHT : COLOR_MENU);
+                                       else
+                                               dc.FillRect(&rcButn, COLOR_MENU);
+                               }
+                               else
+                               {
+                                       COLORREF crTxt = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE));
+                                       COLORREF crBk = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT));
+                                       CBrush hbr(CDCHandle::GetHalftoneBrush());
+                                       dc.SetBrushOrg(rcButn.left, rcButn.top);
+                                       dc.FillRect(&rcButn, hbr);
+                                       dc.SetTextColor(crTxt);
+                                       dc.SetBkColor(crBk);
+                               }
+
+                               // draw disabled or normal
+                               if(!bDisabled)
+                               {
+                                       // draw pushed-in or popped-out edge
+                                       if(bSelected || bChecked)
+                                       {
+                                               RECT rc2 = rcButn;
+                                               dc.DrawEdge(&rc2, bChecked ? BDR_SUNKENOUTER : BDR_RAISEDINNER, BF_RECT);
+                                       }
+                                       // draw the image
+                                       ::ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT);
+                               }
+                               else
+                               {
+                                       HBRUSH hBrushBackground = bChecked ? NULL : ::GetSysColorBrush(COLOR_MENU);
+                                       pT->DrawBitmapDisabled(dc, iButton, point, hBrushBackground);
+                               }
+                       }
+                       else
+                       {
+                               // no image - look for custom checked/unchecked bitmaps
+                               CMenuItemInfo info;
+                               info.fMask = MIIM_CHECKMARKS | MIIM_TYPE;
+                               ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info);
+                               if(bChecked || info.hbmpUnchecked != NULL)
+                               {
+                                       BOOL bRadio = ((info.fType & MFT_RADIOCHECK) != 0);
+                                       bHasImage = pT->DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked);
+                               }
+                       }
+
+                       // draw item text
+                       int cxButn = m_szButton.cx;
+                       COLORREF colorBG = ::GetSysColor(bSelected ? COLOR_HIGHLIGHT : COLOR_MENU);
+                       if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT)
+                       {
+                               RECT rcBG = rcItem;
+                               if(bHasImage)
+                                       rcBG.left += cxButn + s_kcxGap;
+                               dc.FillRect(&rcBG, bSelected ? COLOR_HIGHLIGHT : COLOR_MENU);
+                       }
+
+                       // calc text rectangle and colors
+                       RECT rcText = rcItem;
+                       rcText.left += cxButn + s_kcxGap + s_kcxTextMargin;
+                       rcText.right -= cxButn;
+                       dc.SetBkMode(TRANSPARENT);
+                       COLORREF colorText = ::GetSysColor(bDisabled ?  (bSelected ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT));
+
+                       // font already selected by Windows
+                       if(bDisabled && (!bSelected || colorText == colorBG))
+                       {
+                               // disabled - draw shadow text shifted down and right 1 pixel (unles selected)
+                               RECT rcDisabled = rcText;
+                               ::OffsetRect(&rcDisabled, 1, 1);
+                               pT->DrawMenuText(dc, rcDisabled, pmd->lpstrText, ::GetSysColor(COLOR_3DHILIGHT));
+                       }
+                       pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText); // finally!
+               }
+       }
+
+       void DrawItemFlat(LPDRAWITEMSTRUCT lpDrawItemStruct)
+       {
+               _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData;
+               CDCHandle dc = lpDrawItemStruct->hDC;
+               const RECT& rcItem = lpDrawItemStruct->rcItem;
+               T* pT = static_cast<T*>(this);
+
+#ifndef COLOR_MENUHILIGHT
+               const int COLOR_MENUHILIGHT = 29;
+#endif // !COLOR_MENUHILIGHT
+
+               BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED;
+               BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
+               BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED;
+
+               // paint background
+               if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT)
+               {
+                       if(bSelected)
+                       {
+                               dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_MENUHILIGHT));
+                               dc.FrameRect(&rcItem, ::GetSysColorBrush(COLOR_HIGHLIGHT));
+                       }
+                       else
+                       {
+                               dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_MENU));
+                       }
+               }
+
+               if(pmd->fType & MFT_SEPARATOR)
+               {
+                       // draw separator
+                       RECT rc = rcItem;
+                       rc.top += (rc.bottom - rc.top) / 2;      // vertical center
+                       dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP);   // draw separator line
+               }
+               else            // not a separator
+               {
+                       if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1)
+                               bSelected = FALSE;
+                       RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy };   // button rect
+                       ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2);          // center vertically
+
+                       // draw background and border for checked items
+                       if(bChecked)
+                       {
+                               RECT rcCheck = rcButn;
+                               ::InflateRect(&rcCheck, -1, -1);
+                               if(bSelected)
+                                       dc.FillRect(&rcCheck, ::GetSysColorBrush(COLOR_MENU));
+                               dc.FrameRect(&rcCheck, ::GetSysColorBrush(COLOR_HIGHLIGHT));
+                       }
+
+                       int iButton = pmd->iButton;
+                       if(iButton >= 0)
+                       {
+                               // calc drawing point
+                               SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy };
+                               sz.cx /= 2;
+                               sz.cy /= 2;
+                               POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy };
+
+                               // draw disabled or normal
+                               if(!bDisabled)
+                               {
+                                       ::ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT);
+                               }
+                               else
+                               {
+                                       HBRUSH hBrushBackground = ::GetSysColorBrush((bSelected && !(bDisabled && bChecked)) ? COLOR_MENUHILIGHT : COLOR_MENU);
+                                       HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW);
+                                       pT->DrawBitmapDisabled(dc, iButton, point, hBrushBackground, hBrushBackground, hBrushDisabledImage);
+                               }
+                       }
+                       else
+                       {
+                               // no image - look for custom checked/unchecked bitmaps
+                               CMenuItemInfo info;
+                               info.fMask = MIIM_CHECKMARKS | MIIM_TYPE;
+                               ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info);
+                               if(bChecked || info.hbmpUnchecked != NULL)
+                               {
+                                       BOOL bRadio = ((info.fType & MFT_RADIOCHECK) != 0);
+                                       pT->DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked);
+                               }
+                       }
+
+                       // draw item text
+                       int cxButn = m_szButton.cx;
+                       // calc text rectangle and colors
+                       RECT rcText = rcItem;
+                       rcText.left += cxButn + s_kcxGap + s_kcxTextMargin;
+                       rcText.right -= cxButn;
+                       dc.SetBkMode(TRANSPARENT);
+                       COLORREF colorText = ::GetSysColor(bDisabled ?  (bSelected ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT));
+
+                       pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText); // finally!
+               }
+       }
+
+       void DrawMenuText(CDCHandle& dc, RECT& rc, LPCTSTR lpstrText, COLORREF color)
+       {
+               int nTab = -1;
+               for(int i = 0; i < lstrlen(lpstrText); i++)
+               {
+                       if(lpstrText[i] == _T('\t'))
+                       {
+                               nTab = i;
+                               break;
+                       }
+               }
+               dc.SetTextColor(color);
+               dc.DrawText(lpstrText, nTab, &rc, DT_SINGLELINE | DT_LEFT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX));
+               if(nTab != -1)
+                       dc.DrawText(&lpstrText[nTab + 1], -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX));
+       }
+
+       void DrawBitmapDisabled(CDCHandle& dc, int nImage, POINT point,
+                       HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE),
+                       HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT),
+                       HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW))
+       {
+#if (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
+               if(m_bAlphaImages)
+               {
+                       IMAGELISTDRAWPARAMS ildp = { 0 };
+                       ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
+                       ildp.himl = m_hImageList;
+                       ildp.i = nImage;
+                       ildp.hdcDst = dc;
+                       ildp.x = point.x;
+                       ildp.y = point.y;
+                       ildp.cx = 0;
+                       ildp.cy = 0;
+                       ildp.xBitmap = 0;
+                       ildp.yBitmap = 0;
+                       ildp.fStyle = ILD_TRANSPARENT;
+                       ildp.fState = ILS_SATURATE;
+                       ildp.Frame = 0;
+                       ::ImageList_DrawIndirect(&ildp);
+               }
+               else
+#endif // (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
+               {
+                       // create memory DC
+                       CDC dcMem;
+                       dcMem.CreateCompatibleDC(dc);
+                       // create mono or color bitmap
+                       CBitmap bmp;
+                       bmp.CreateCompatibleBitmap(dc, m_szBitmap.cx, m_szBitmap.cy);
+                       ATLASSERT(bmp.m_hBitmap != NULL);
+                       // draw image into memory DC--fill BG white first
+                       HBITMAP hBmpOld = dcMem.SelectBitmap(bmp);
+                       dcMem.PatBlt(0, 0, m_szBitmap.cx, m_szBitmap.cy, WHITENESS);
+                       // If white is the text color, we can't use the normal painting since
+                       // it would blend with the WHITENESS, but the mask is OK
+                       UINT uDrawStyle = (::GetSysColor(COLOR_BTNTEXT) == RGB(255, 255, 255)) ? ILD_MASK : ILD_NORMAL;
+                       ::ImageList_Draw(m_hImageList, nImage, dcMem, 0, 0, uDrawStyle);
+                       dc.DitherBlt(point.x, point.y, m_szBitmap.cx, m_szBitmap.cy, dcMem, NULL, 0, 0, hBrushBackground, hBrush3DEffect, hBrushDisabledImage);
+                       dcMem.SelectBitmap(hBmpOld);   // restore
+               }
+       }
+
+       // old name
+       BOOL Draw3DCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL bDisabled, BOOL bRadio, HBITMAP hBmpCheck)
+       {
+               return DrawCheckmark(dc, rc, bSelected, bDisabled, bRadio, hBmpCheck);
+       }
+
+       BOOL DrawCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL bDisabled, BOOL bRadio, HBITMAP hBmpCheck)
+       {
+               // get checkmark bitmap, if none, use Windows standard
+               SIZE size = { 0, 0 };
+               CBitmapHandle bmp = hBmpCheck;
+               if(hBmpCheck != NULL)
+               {
+                       bmp.GetSize(size);
+               }
+               else
+               {
+                       size.cx = ::GetSystemMetrics(SM_CXMENUCHECK); 
+                       size.cy = ::GetSystemMetrics(SM_CYMENUCHECK); 
+                       bmp.CreateCompatibleBitmap(dc, size.cx, size.cy);
+                       ATLASSERT(bmp.m_hBitmap != NULL);
+               }
+               // center bitmap in caller's rectangle
+               RECT rcDest = rc;
+               if((rc.right - rc.left) > size.cx)
+               {
+                       rcDest.left = rc.left + (rc.right - rc.left - size.cx) / 2;
+                       rcDest.right = rcDest.left + size.cx;
+               }
+               if((rc.bottom - rc.top) > size.cy)
+               {
+                       rcDest.top = rc.top + (rc.bottom - rc.top - size.cy) / 2;
+                       rcDest.bottom = rcDest.top + size.cy;
+               }
+               // paint background
+               if(!m_bFlatMenus)
+               {
+                       if(bSelected && !bDisabled)
+                       {
+                               dc.FillRect(&rcDest, COLOR_MENU);
+                       }
+                       else
+                       {
+                               COLORREF clrTextOld = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE));
+                               COLORREF clrBkOld = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT));
+                               CBrush hbr(CDCHandle::GetHalftoneBrush());
+                               dc.SetBrushOrg(rcDest.left, rcDest.top);
+                               dc.FillRect(&rcDest, hbr);
+                               dc.SetTextColor(clrTextOld);
+                               dc.SetBkColor(clrBkOld);
+                       }
+               }
+
+               // create source image
+               CDC dcSource;
+               dcSource.CreateCompatibleDC(dc);
+               HBITMAP hBmpOld = dcSource.SelectBitmap(bmp);
+               // set colors
+               const COLORREF clrBlack = RGB(0, 0, 0);
+               const COLORREF clrWhite = RGB(255, 255, 255);
+               COLORREF clrTextOld = dc.SetTextColor(clrBlack);
+               COLORREF clrBkOld = dc.SetBkColor(clrWhite);
+               // create mask
+               CDC dcMask;
+               dcMask.CreateCompatibleDC(dc);
+               CBitmap bmpMask;
+               bmpMask.CreateBitmap(size.cx, size.cy, 1, 1, NULL);
+               HBITMAP hBmpOld1 = dcMask.SelectBitmap(bmpMask);
+
+               // draw the checkmark transparently
+               int cx = rcDest.right - rcDest.left;
+               int cy = rcDest.bottom - rcDest.top;
+               if(hBmpCheck != NULL)
+               {
+                       // build mask based on transparent color        
+                       dcSource.SetBkColor(m_clrMask);
+                       dcMask.SetBkColor(clrBlack);
+                       dcMask.SetTextColor(clrWhite);
+                       dcMask.BitBlt(0, 0, size.cx, size.cy, dcSource, 0, 0, SRCCOPY);
+                       // draw bitmap using the mask
+                       dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, SRCINVERT);
+                       dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, SRCAND);
+                       dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, SRCINVERT);
+               }
+               else
+               {
+                       const DWORD ROP_DSno = 0x00BB0226L;
+                       const DWORD ROP_DSa = 0x008800C6L;
+                       const DWORD ROP_DSo = 0x00EE0086L;
+                       const DWORD ROP_DSna = 0x00220326L;
+
+                       // draw mask
+                       RECT rcSource = { 0, 0, min(size.cx, rc.right - rc.left), min(size.cy, rc.bottom - rc.top) };
+                       dcMask.DrawFrameControl(&rcSource, DFC_MENU, bRadio ? DFCS_MENUBULLET : DFCS_MENUCHECK);
+
+                       // draw shadow if disabled
+                       if(!m_bFlatMenus && bDisabled)
+                       {
+                               // offset by one pixel
+                               int x = rcDest.left + 1;
+                               int y = rcDest.top + 1;
+                               // paint source bitmap
+                               const int nColor = COLOR_3DHILIGHT;
+                               dcSource.FillRect(&rcSource, nColor);
+                               // draw checkmark - special case black and white colors
+                               COLORREF clrCheck = ::GetSysColor(nColor);
+                               if(clrCheck == clrWhite)
+                               {
+                                       dc.BitBlt(x, y, cx, cy, dcMask,  0, 0,   ROP_DSno);
+                                       dc.BitBlt(x, y, cx, cy, dcSource, 0, 0, ROP_DSa);
+                               }
+                               else
+                               {
+                                       if(clrCheck != clrBlack)
+                                       {
+                                               ATLASSERT(dcSource.GetTextColor() == clrBlack);
+                                               ATLASSERT(dcSource.GetBkColor() == clrWhite);
+                                               dcSource.BitBlt(0, 0, size.cx, size.cy, dcMask, 0, 0, ROP_DSna);
+                                       }
+                                       dc.BitBlt(x, y, cx, cy, dcMask,  0,  0,  ROP_DSa);
+                                       dc.BitBlt(x, y, cx, cy, dcSource, 0, 0, ROP_DSo);
+                               }
+                       }
+
+                       // paint source bitmap
+                       const int nColor = bDisabled ? COLOR_BTNSHADOW : COLOR_MENUTEXT;
+                       dcSource.FillRect(&rcSource, nColor);
+                       // draw checkmark - special case black and white colors
+                       COLORREF clrCheck = ::GetSysColor(nColor);
+                       if(clrCheck == clrWhite)
+                       {
+                               dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask,  0, 0,   ROP_DSno);
+                               dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, ROP_DSa);
+                       }
+                       else
+                       {
+                               if(clrCheck != clrBlack)
+                               {
+                                       ATLASSERT(dcSource.GetTextColor() == clrBlack);
+                                       ATLASSERT(dcSource.GetBkColor() == clrWhite);
+                                       dcSource.BitBlt(0, 0, size.cx, size.cy, dcMask, 0, 0, ROP_DSna);
+                               }
+                               dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask,  0,  0,  ROP_DSa);
+                               dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, ROP_DSo);
+                       }
+               }
+               // restore all
+               dc.SetTextColor(clrTextOld);
+               dc.SetBkColor(clrBkOld);
+               dcSource.SelectBitmap(hBmpOld);
+               dcMask.SelectBitmap(hBmpOld1);
+               if(hBmpCheck == NULL)
+                       bmp.DeleteObject();
+               // draw pushed-in hilight
+               if(!m_bFlatMenus && !bDisabled)
+               {
+                       if(rc.right - rc.left > size.cx)
+                               ::InflateRect(&rcDest, 1,1);   // inflate checkmark by one pixel all around
+                       dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
+               }
+
+               return TRUE;
+       }
+
+       void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
+       {
+               _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData;
+
+               if(pmd->fType & MFT_SEPARATOR)   // separator - use half system height and zero width
+               {
+                       lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU) / 2;
+                       lpMeasureItemStruct->itemWidth  = 0;
+               }
+               else
+               {
+                       // compute size of text - use DrawText with DT_CALCRECT
+                       CWindowDC dc(NULL);
+                       CFont fontBold;
+                       HFONT hOldFont = NULL;
+                       if(pmd->fState & MFS_DEFAULT)
+                       {
+                               // need bold version of font
+                               LOGFONT lf = { 0 };
+                               m_fontMenu.GetLogFont(lf);
+                               lf.lfWeight += 200;
+                               fontBold.CreateFontIndirect(&lf);
+                               ATLASSERT(fontBold.m_hFont != NULL);
+                               hOldFont = dc.SelectFont(fontBold);
+                       }
+                       else
+                       {
+                               hOldFont = dc.SelectFont(m_fontMenu);
+                       }
+
+                       RECT rcText = { 0, 0, 0, 0 };
+                       dc.DrawText(pmd->lpstrText, -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
+                       int cx = rcText.right - rcText.left;
+                       dc.SelectFont(hOldFont);
+
+                       LOGFONT lf = { 0 };
+                       m_fontMenu.GetLogFont(lf);
+                       int cy = lf.lfHeight;
+                       if(cy < 0)
+                               cy = -cy;
+                       const int cyMargin = 8;
+                       cy += cyMargin;
+
+                       // height of item is the bigger of these two
+                       lpMeasureItemStruct->itemHeight = max(cy, (int)m_szButton.cy);
+
+                       // width is width of text plus a bunch of stuff
+                       cx += 2 * s_kcxTextMargin;   // L/R margin for readability
+                       cx += s_kcxGap;              // space between button and menu text
+                       cx += 2 * m_szButton.cx;     // button width (L=button; R=empty margin)
+                       cx += m_cxExtraSpacing;      // extra between item text and accelerator keys
+
+                       // Windows adds 1 to returned value
+                       cx -= ::GetSystemMetrics(SM_CXMENUCHECK) - 1;
+                       lpMeasureItemStruct->itemWidth = cx;   // done deal
+               }
+       }
+
+// Implementation - Hook procs
+       static LRESULT CALLBACK CreateHookProc(int nCode, WPARAM wParam, LPARAM lParam)
+       {
+               const int cchClassName = 7;
+               TCHAR szClassName[cchClassName] = { 0 };
+
+               if(nCode == HCBT_CREATEWND)
+               {
+                       HWND hWndMenu = (HWND)wParam;
+#ifdef _CMDBAR_EXTRA_TRACE
+                       ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_CREATEWND (HWND = %8.8X)\n"), hWndMenu);
+#endif
+
+                       ::GetClassName(hWndMenu, szClassName, cchClassName);
+                       if(!lstrcmp(_T("#32768"), szClassName))
+                               s_pCurrentBar->m_stackMenuWnd.Push(hWndMenu);
+               }
+               else if(nCode == HCBT_DESTROYWND)
+               {
+                       HWND hWndMenu = (HWND)wParam;
+#ifdef _CMDBAR_EXTRA_TRACE
+                       ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_DESTROYWND (HWND = %8.8X)\n"), hWndMenu);
+#endif
+
+                       ::GetClassName(hWndMenu, szClassName, cchClassName);
+                       if(!lstrcmp(_T("#32768"), szClassName))
+                       {
+                               ATLASSERT(hWndMenu == s_pCurrentBar->m_stackMenuWnd.GetCurrent());
+                               s_pCurrentBar->m_stackMenuWnd.Pop();
+                       }
+               }
+
+               return ::CallNextHookEx(s_hCreateHook, nCode, wParam, lParam);
+       }
+
+       static LRESULT CALLBACK MessageHookProc(int nCode, WPARAM wParam, LPARAM lParam)
+       {
+               LPMSG pMsg = (LPMSG)lParam;
+
+               if(nCode == HC_ACTION && wParam == PM_REMOVE && pMsg->message != GetGetBarMessage() && pMsg->message != WM_FORWARDMSG)
+               {
+                       CCommandBarCtrlBase* pCmdBar = NULL;
+                       HWND hWnd = pMsg->hwnd;
+                       DWORD dwPID = 0;
+                       while(pCmdBar == NULL && hWnd != NULL)
+                       {
+                               pCmdBar = (CCommandBarCtrlBase*)::SendMessage(hWnd, GetGetBarMessage(), (WPARAM)&dwPID, 0L);
+                               hWnd = ::GetParent(hWnd);
+                       }
+
+                       if(pCmdBar != NULL && dwPID == GetCurrentProcessId())
+                       {
+                               pCmdBar->m_hWndHook = pMsg->hwnd;
+                               ATLASSERT(pCmdBar->IsCommandBarBase());
+
+                               if(::IsWindow(pCmdBar->m_hWnd))
+                                       pCmdBar->SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
+                               else
+                                       ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook skipping message, can't find command bar!\n"));
+                       }
+               }
+
+               LRESULT lRet = 0;
+               ATLASSERT(s_pmapMsgHook != NULL);
+               if(s_pmapMsgHook != NULL)
+               {
+                       DWORD dwThreadID = ::GetCurrentThreadId();
+                       _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID);
+                       if(pData != NULL)
+                       {
+                               lRet = ::CallNextHookEx(pData->hMsgHook, nCode, wParam, lParam);
+                       }
+               }
+               return lRet;
+       }
+
+// Implementation
+       void DoPopupMenu(int nIndex, bool bAnimate)
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - DoPopupMenu, bAnimate = %s\n"), bAnimate ? "true" : "false");
+#endif
+
+               // Menu animation flags
+#ifndef TPM_VERPOSANIMATION
+               const UINT TPM_VERPOSANIMATION = 0x1000L;
+#endif
+#ifndef TPM_NOANIMATION
+               const UINT TPM_NOANIMATION = 0x4000L;
+#endif
+               T* pT = static_cast<T*>(this);
+
+               // get popup menu and it's position
+               RECT rect = { 0 };
+               GetItemRect(nIndex, &rect);
+               POINT pt = { rect.left, rect.bottom };
+               MapWindowPoints(NULL, &pt, 1);
+               MapWindowPoints(NULL, &rect);
+               TPMPARAMS TPMParams = { 0 };
+               TPMParams.cbSize = sizeof(TPMPARAMS);
+               TPMParams.rcExclude = rect;
+               HMENU hMenuPopup = ::GetSubMenu(m_hMenu, nIndex);
+               ATLASSERT(hMenuPopup != NULL);
+
+               // get button ID
+               TBBUTTON tbb = { 0 };
+               GetButton(nIndex, &tbb);
+               int nCmdID = tbb.idCommand;
+
+               m_nPopBtn = nIndex;   // remember current button's index
+
+               // press button and display popup menu
+               PressButton(nCmdID, TRUE);
+               SetHotItem(nCmdID);
+               pT->DoTrackPopupMenu(hMenuPopup, TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN |
+                       (s_bW2K ? (bAnimate ? TPM_VERPOSANIMATION : TPM_NOANIMATION) : 0), pt.x, pt.y, &TPMParams);
+               PressButton(nCmdID, FALSE);
+               if(::GetFocus() != m_hWnd)
+                       SetHotItem(-1);
+
+               m_nPopBtn = -1;   // restore
+
+               // eat next message if click is on the same button
+               MSG msg = { 0 };
+               if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rect, msg.pt))
+                       ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
+
+               // check if another popup menu should be displayed
+               if(m_nNextPopBtn != -1)
+               {
+                       PostMessage(GetAutoPopupMessage(), m_nNextPopBtn & 0xFFFF);
+                       if(!(m_nNextPopBtn & 0xFFFF0000) && !m_bPopupItem)
+                               PostMessage(WM_KEYDOWN, VK_DOWN, 0);
+                       m_nNextPopBtn = -1;
+               }
+               else
+               {
+                       m_bContextMenu = false;
+                       // If user didn't hit escape, give focus back
+                       if(!m_bEscapePressed)
+                       {
+                               if(m_bUseKeyboardCues && m_bShowKeyboardCues)
+                                       m_bAllowKeyboardCues = false;
+                               pT->GiveFocusBack();
+                       }
+                       else
+                       {
+                               SetHotItem(nCmdID);
+                               SetAnchorHighlight(TRUE);
+                       }
+               }
+       }
+
+       BOOL DoTrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL)
+       {
+               CMenuHandle menuPopup = hMenu;
+
+               CWindowCreateCriticalSectionLock lock;
+               if(FAILED(lock.Lock()))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::DoTrackPopupMenu.\n"));
+                       ATLASSERT(FALSE);
+                       return FALSE;
+               }
+
+               ATLASSERT(s_hCreateHook == NULL);
+
+               s_pCurrentBar = static_cast<CCommandBarCtrlBase*>(this);
+
+               s_hCreateHook = ::SetWindowsHookEx(WH_CBT, CreateHookProc, ModuleHelper::GetModuleInstance(), GetCurrentThreadId());
+               ATLASSERT(s_hCreateHook != NULL);
+
+               m_bPopupItem = false;
+               m_bMenuActive = true;
+
+               BOOL bTrackRet = menuPopup.TrackPopupMenuEx(uFlags, x, y, m_hWnd, lpParams);
+               m_bMenuActive = false;
+
+               ::UnhookWindowsHookEx(s_hCreateHook);
+
+               s_hCreateHook = NULL;
+               s_pCurrentBar = NULL;
+
+               lock.Unlock();
+
+               // cleanup - convert menus back to original state
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - TrackPopupMenu - cleanup\n"));
+#endif
+
+               ATLASSERT(m_stackMenuWnd.GetSize() == 0);
+
+               UpdateWindow();
+               ATL::CWindow wndTL = GetTopLevelParent();
+               wndTL.UpdateWindow();
+
+               // restore the menu items to the previous state for all menus that were converted
+               if(m_bImagesVisible)
+               {
+                       HMENU hMenuSav = NULL;
+                       while((hMenuSav = m_stackMenuHandle.Pop()) != NULL)
+                       {
+                               menuPopup = hMenuSav;
+                               BOOL bRet = FALSE;
+                               // restore state and delete menu item data
+                               for(int i = 0; i < menuPopup.GetMenuItemCount(); i++)
+                               {
+                                       CMenuItemInfo mii;
+                                       mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID;
+                                       bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii);
+                                       ATLASSERT(bRet);
+
+                                       _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData;
+                                       if(pMI != NULL && pMI->IsCmdBarMenuItem())
+                                       {
+                                               mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
+                                               mii.fType = pMI->fType;
+                                               mii.fState = pMI->fState;
+                                               mii.dwTypeData = pMI->lpstrText;
+                                               mii.cch = lstrlen(pMI->lpstrText);
+                                               mii.dwItemData = NULL;
+
+                                               bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii);
+                                               // this one triggers WM_MEASUREITEM
+                                               menuPopup.ModifyMenu(i, MF_BYPOSITION | mii.fType | mii.fState, mii.wID, pMI->lpstrText);
+                                               ATLASSERT(bRet);
+
+                                               delete [] pMI->lpstrText;
+                                               delete pMI;
+                                       }
+                               }
+                       }
+               }
+               return bTrackRet;
+       }
+
+       int GetPreviousMenuItem(int nBtn) const
+       {
+               if(nBtn == -1)
+                       return -1;
+#if (_WIN32_IE >= 0x0500)
+               RECT rcClient;
+               GetClientRect(&rcClient);
+#endif // (_WIN32_IE >= 0x0500)
+               int nNextBtn;
+               for(nNextBtn = nBtn - 1; nNextBtn != nBtn; nNextBtn--)
+               {
+                       if(nNextBtn < 0)
+                               nNextBtn = ::GetMenuItemCount(m_hMenu) - 1;
+                       TBBUTTON tbb = { 0 };
+                       GetButton(nNextBtn, &tbb);
+#if (_WIN32_IE >= 0x0500)
+                       RECT rcBtn;
+                       GetItemRect(nNextBtn, &rcBtn);
+                       if(rcBtn.right > rcClient.right)
+                       {
+                               nNextBtn = -2;   // chevron
+                               break;
+                       }
+#endif // (_WIN32_IE >= 0x0500)
+                       if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0)
+                               break;
+               }
+               return (nNextBtn != nBtn) ? nNextBtn : -1;
+       }
+
+       int GetNextMenuItem(int nBtn) const
+       {
+               if(nBtn == -1)
+                       return -1;
+#if (_WIN32_IE >= 0x0500)
+               RECT rcClient = { 0 };
+               GetClientRect(&rcClient);
+#endif // (_WIN32_IE >= 0x0500)
+               int nNextBtn = 0;
+               int nCount = ::GetMenuItemCount(m_hMenu);
+               for(nNextBtn = nBtn + 1; nNextBtn != nBtn; nNextBtn++)
+               {
+                       if(nNextBtn >= nCount)
+                               nNextBtn = 0;
+                       TBBUTTON tbb = { 0 };
+                       GetButton(nNextBtn, &tbb);
+#if (_WIN32_IE >= 0x0500)
+                       RECT rcBtn = { 0 };
+                       GetItemRect(nNextBtn, &rcBtn);
+                       if(rcBtn.right > rcClient.right)
+                       {
+                               nNextBtn = -2;   // chevron
+                               break;
+                       }
+#endif // (_WIN32_IE >= 0x0500)
+                       if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0)
+                               break;
+               }
+               return (nNextBtn != nBtn) ? nNextBtn : -1;
+       }
+
+#if (_WIN32_IE >= 0x0500)
+       bool DisplayChevronMenu()
+       {
+               // assume we are in a rebar
+               HWND hWndReBar = GetParent();
+               int nCount = (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L);
+               bool bRet = false;
+               for(int i = 0; i < nCount; i++)
+               {
+                       REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_STYLE };
+                       BOOL bRetBandInfo = (BOOL)::SendMessage(hWndReBar, RB_GETBANDINFO, i, (LPARAM)&rbbi);
+                       if(bRetBandInfo && rbbi.hwndChild == m_hWnd)
+                       {
+                               if((rbbi.fStyle & RBBS_USECHEVRON) != 0)
+                               {
+                                       ::PostMessage(hWndReBar, RB_PUSHCHEVRON, i, 0L);
+                                       PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+                                       bRet = true;
+                               }
+                               break;
+                       }
+               }
+               return bRet;
+       }
+#endif // (_WIN32_IE >= 0x0500)
+
+       void GetSystemSettings()
+       {
+               // refresh our font
+               NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
+               BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+               ATLASSERT(bRet);
+               if(bRet)
+               {
+                       LOGFONT logfont = { 0 };
+                       if(m_fontMenu.m_hFont != NULL)
+                               m_fontMenu.GetLogFont(logfont);
+                       if(logfont.lfHeight != info.lfMenuFont.lfHeight ||
+                          logfont.lfWidth != info.lfMenuFont.lfWidth ||
+                          logfont.lfEscapement != info.lfMenuFont.lfEscapement ||
+                          logfont.lfOrientation != info.lfMenuFont.lfOrientation ||
+                          logfont.lfWeight != info.lfMenuFont.lfWeight ||
+                          logfont.lfItalic != info.lfMenuFont.lfItalic ||
+                          logfont.lfUnderline != info.lfMenuFont.lfUnderline ||
+                          logfont.lfStrikeOut != info.lfMenuFont.lfStrikeOut ||
+                          logfont.lfCharSet != info.lfMenuFont.lfCharSet ||
+                          logfont.lfOutPrecision != info.lfMenuFont.lfOutPrecision ||
+                          logfont.lfClipPrecision != info.lfMenuFont.lfClipPrecision ||
+                          logfont.lfQuality != info.lfMenuFont.lfQuality ||
+                          logfont.lfPitchAndFamily != info.lfMenuFont.lfPitchAndFamily ||
+                          lstrcmp(logfont.lfFaceName, info.lfMenuFont.lfFaceName) != 0)
+                       {
+                               HFONT hFontMenu = ::CreateFontIndirect(&info.lfMenuFont);
+                               ATLASSERT(hFontMenu != NULL);
+                               if(hFontMenu != NULL)
+                               {
+                                       if(m_fontMenu.m_hFont != NULL)
+                                               m_fontMenu.DeleteObject();
+                                       m_fontMenu.Attach(hFontMenu);
+                                       SetFont(m_fontMenu);
+                                       AddStrings(_T("NS\0"));   // for proper item height
+                                       AutoSize();
+                               }
+                       }
+               }
+
+               // check if we need extra spacing for menu item text
+               CWindowDC dc(m_hWnd);
+               HFONT hFontOld = dc.SelectFont(m_fontMenu);
+               RECT rcText = { 0, 0, 0, 0 };
+               dc.DrawText(_T("\t"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
+               if((rcText.right - rcText.left) < 4)
+               {
+                       ::SetRectEmpty(&rcText);
+                       dc.DrawText(_T("x"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
+                       m_cxExtraSpacing = rcText.right - rcText.left;
+               }
+               else
+               {
+                       m_cxExtraSpacing = 0;
+               }
+               dc.SelectFont(hFontOld);
+
+               // get Windows version
+               OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
+               ::GetVersionEx(&ovi);
+
+               // query keyboard cues mode (Windows 2000 or later)
+               if(ovi.dwMajorVersion >= 5)
+               {
+#ifndef SPI_GETKEYBOARDCUES
+                       const UINT SPI_GETKEYBOARDCUES = 0x100A;
+#endif // !SPI_GETKEYBOARDCUES
+                       BOOL bRetVal = TRUE;
+                       bRet = ::SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &bRetVal, 0);
+                       m_bUseKeyboardCues = (bRet && !bRetVal);
+                       m_bAllowKeyboardCues = true;
+                       ShowKeyboardCues(!m_bUseKeyboardCues);
+               }
+
+               // query flat menu mode (Windows XP or later)
+               if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5))
+               {
+#ifndef SPI_GETFLATMENU
+                       const UINT SPI_GETFLATMENU = 0x1022;
+#endif // !SPI_GETFLATMENU
+                       BOOL bRetVal = FALSE;
+                       bRet = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &bRetVal, 0);
+                       m_bFlatMenus = (bRet && bRetVal);
+               }
+
+#if _WTL_CMDBAR_VISTA_MENUS
+               // check if we should use Vista menus
+               bool bVistaMenus = (RunTimeHelper::IsVista() && RunTimeHelper::IsCommCtrl6() && ((m_dwExtendedStyle & CBR_EX_NOVISTAMENUS) == 0));
+
+               if(bVistaMenus)
+               {
+                       HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
+                       if(hThemeDLL != NULL)
+                       {
+                               typedef BOOL (STDAPICALLTYPE *PFN_IsThemeActive)();
+                               PFN_IsThemeActive pfnIsThemeActive = (PFN_IsThemeActive)::GetProcAddress(hThemeDLL, "IsThemeActive");
+                               ATLASSERT(pfnIsThemeActive != NULL);
+                               bVistaMenus = bVistaMenus && (pfnIsThemeActive != NULL) && (pfnIsThemeActive() != FALSE);
+
+                               typedef BOOL (STDAPICALLTYPE *PFN_IsAppThemed)();
+                               PFN_IsAppThemed pfnIsAppThemed = (PFN_IsAppThemed)::GetProcAddress(hThemeDLL, "IsAppThemed");
+                               ATLASSERT(pfnIsAppThemed != NULL);
+                               bVistaMenus = bVistaMenus && (pfnIsAppThemed != NULL) && (pfnIsAppThemed() != FALSE);
+
+                               ::FreeLibrary(hThemeDLL);
+                       }
+               }
+
+               if(!bVistaMenus && m_bVistaMenus && (m_hMenu != NULL) && (m_arrCommand.GetSize() > 0))
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->_RemoveVistaBitmapsFromMenu();
+               }
+
+               m_bVistaMenus = bVistaMenus;
+#endif // _WTL_CMDBAR_VISTA_MENUS
+
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("CmdBar - GetSystemSettings:\n     m_bFlatMenus = %s\n     m_bUseKeyboardCues = %s     m_bVistaMenus = %s\n"),
+                       m_bFlatMenus ? "true" : "false", m_bUseKeyboardCues ? "true" : "false", m_bVistaMenus ? "true" : "false");
+#endif
+       }
+
+// Implementation - alternate focus mode support
+       void TakeFocus()
+       {
+               if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_hWndFocus == NULL)
+                       m_hWndFocus = ::GetFocus();
+               SetFocus();
+       }
+
+       void GiveFocusBack()
+       {
+               if(m_bParentActive)
+               {
+                       if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && ::IsWindow(m_hWndFocus))
+                               ::SetFocus(m_hWndFocus);
+                       else if(!(m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_wndParent.IsWindow())
+                               m_wndParent.SetFocus();
+               }
+               m_hWndFocus = NULL;
+               SetAnchorHighlight(FALSE);
+               if(m_bUseKeyboardCues && m_bShowKeyboardCues)
+                       ShowKeyboardCues(false);
+               m_bSkipPostDown = false;
+       }
+
+       void ShowKeyboardCues(bool bShow)
+       {
+               m_bShowKeyboardCues = bShow;
+               SetDrawTextFlags(DT_HIDEPREFIX, m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX);
+               Invalidate();
+               UpdateWindow();
+       }
+
+// Implementation - internal message helpers
+       static UINT GetAutoPopupMessage()
+       {
+               static UINT uAutoPopupMessage = 0;
+               if(uAutoPopupMessage == 0)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::GetAutoPopupMessage.\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(uAutoPopupMessage == 0)
+                               uAutoPopupMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalAutoPopupMsg"));
+
+                       lock.Unlock();
+               }
+               ATLASSERT(uAutoPopupMessage != 0);
+               return uAutoPopupMessage;
+       }
+
+       static UINT GetGetBarMessage()
+       {
+               static UINT uGetBarMessage = 0;
+               if(uGetBarMessage == 0)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::GetGetBarMessage.\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(uGetBarMessage == 0)
+                               uGetBarMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalGetBarMsg"));
+
+                       lock.Unlock();
+               }
+               ATLASSERT(uGetBarMessage != 0);
+               return uGetBarMessage;
+       }
+
+// Implementation
+       bool CreateInternalImageList(int cImages)
+       {
+               UINT uFlags = (m_bAlphaImages ? ILC_COLOR32 : ILC_COLOR24) | ILC_MASK;
+               m_hImageList = ::ImageList_Create(m_szBitmap.cx, m_szBitmap.cy, uFlags, cImages, 1);
+               ATLASSERT(m_hImageList != NULL);
+               return (m_hImageList != NULL);
+       }
+
+// Implementation - support for Vista menus
+#if _WTL_CMDBAR_VISTA_MENUS
+       void _AddVistaBitmapsFromImageList(int nStartIndex, int nCount)
+       {
+               // Create display compatible memory DC
+               HDC hDC = ::GetDC(NULL);
+               CDC dcMem;
+               dcMem.CreateCompatibleDC(hDC);
+               HBITMAP hBitmapSave = dcMem.GetCurrentBitmap();
+
+               T* pT = static_cast<T*>(this);
+               // Create bitmaps for all menu items
+               for(int i = 0; i < nCount; i++)
+               {
+                       HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nStartIndex + i, hDC, dcMem);
+                       dcMem.SelectBitmap(hBitmapSave);
+                       m_arrVistaBitmap.Add(hBitmap);
+               }
+       }
+
+       void _AddVistaBitmapFromImageList(int nIndex)
+       {
+               // Create display compatible memory DC
+               HDC hDC = ::GetDC(NULL);
+               CDC dcMem;
+               dcMem.CreateCompatibleDC(hDC);
+               HBITMAP hBitmapSave = dcMem.GetCurrentBitmap();
+
+               // Create bitmap for menu item
+               T* pT = static_cast<T*>(this);
+               HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, hDC, dcMem);
+
+               // Select saved bitmap back and add bitmap to the array
+               dcMem.SelectBitmap(hBitmapSave);
+               m_arrVistaBitmap.Add(hBitmap);
+       }
+
+       void _ReplaceVistaBitmapFromImageList(int nIndex)
+       {
+               // Delete existing bitmap
+               if(m_arrVistaBitmap[nIndex] != NULL)
+                       ::DeleteObject(m_arrVistaBitmap[nIndex]);
+
+               // Create display compatible memory DC
+               HDC hDC = ::GetDC(NULL);
+               CDC dcMem;
+               dcMem.CreateCompatibleDC(hDC);
+               HBITMAP hBitmapSave = dcMem.GetCurrentBitmap();
+
+               // Create bitmap for menu item
+               T* pT = static_cast<T*>(this);
+               HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, hDC, dcMem);
+
+               // Select saved bitmap back and replace bitmap in the array
+               dcMem.SelectBitmap(hBitmapSave);
+               m_arrVistaBitmap.SetAtIndex(nIndex, hBitmap);
+       }
+
+       HBITMAP _CreateVistaBitmapHelper(int nIndex, HDC hDCSource, HDC hDCTarget)
+       {
+               // Create 32-bit bitmap
+               BITMAPINFO bi = { 0 };
+               bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+               bi.bmiHeader.biWidth = m_szBitmap.cx;
+               bi.bmiHeader.biHeight = m_szBitmap.cy;
+               bi.bmiHeader.biPlanes = 1;
+               bi.bmiHeader.biBitCount = 32;
+               bi.bmiHeader.biCompression = BI_RGB;
+               bi.bmiHeader.biSizeImage = 0;
+               bi.bmiHeader.biXPelsPerMeter = 0;
+               bi.bmiHeader.biYPelsPerMeter = 0;
+               bi.bmiHeader.biClrUsed = 0;
+               bi.bmiHeader.biClrImportant = 0;
+               HBITMAP hBitmap = ::CreateDIBSection(hDCSource, &bi, DIB_RGB_COLORS, NULL, NULL, 0);
+               ATLASSERT(hBitmap != NULL);
+
+               // Select bitmap into target DC and draw from image list to it
+               if(hBitmap != NULL)
+               {
+                       ::SelectObject(hDCTarget, hBitmap);
+
+                       IMAGELISTDRAWPARAMS ildp = { 0 };
+                       ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
+                       ildp.himl = m_hImageList;
+                       ildp.i = nIndex;
+                       ildp.hdcDst = hDCTarget;
+                       ildp.x = 0;
+                       ildp.y = 0;
+                       ildp.cx = 0;
+                       ildp.cy = 0;
+                       ildp.xBitmap = 0;
+                       ildp.yBitmap = 0;
+                       ildp.fStyle = ILD_TRANSPARENT;
+                       ildp.fState = ILS_ALPHA;
+                       ildp.Frame = 255;
+                       ::ImageList_DrawIndirect(&ildp);
+               }
+
+               return hBitmap;
+       }
+
+       void _RemoveVistaBitmapsFromMenu()
+       {
+               CMenuHandle menu = m_hMenu;
+               for(int i = 0; i < m_arrCommand.GetSize(); i++)
+               {
+                       CMenuItemInfo mii;
+                       mii.fMask = MIIM_BITMAP;
+                       mii.hbmpItem = NULL;
+                       menu.SetMenuItemInfo(m_arrCommand[i], FALSE, &mii);
+               }
+       }
+#endif // _WTL_CMDBAR_VISTA_MENUS
+};
+
+
+class CCommandBarCtrl : public CCommandBarCtrlImpl<CCommandBarCtrl>
+{
+public:
+       DECLARE_WND_SUPERCLASS(_T("WTL_CommandBar"), GetWndClassName())
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMDICommandBarCtrl - ATL implementation of Command Bars for MDI apps
+
+template <class T, class TBase = CCommandBarCtrlBase, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CMDICommandBarCtrlImpl : public CCommandBarCtrlImpl< T, TBase, TWinTraits>
+{
+public:
+// Data members
+       ATL::CContainedWindow m_wndMDIClient;
+       bool m_bChildMaximized;
+       HWND m_hWndChildMaximized;
+       HICON m_hIconChildMaximized;
+       int m_nBtnPressed;
+       int m_nBtnWasPressed;
+
+       int m_cxyOffset;      // offset between nonclient elements
+       int m_cxIconWidth;    // small icon width
+       int m_cyIconHeight;   // small icon height
+       int m_cxBtnWidth;     // nonclient button width
+       int m_cyBtnHeight;    // nonclient button height
+       int m_cxLeft;         // left nonclient area width
+       int m_cxRight;        // right nonclient area width
+
+// Theme declarations and data members
+#ifndef _WTL_NO_AUTO_THEME
+#ifndef _UXTHEME_H_
+       typedef HANDLE HTHEME;
+#endif // !_UXTHEME_H_
+       typedef HTHEME (STDAPICALLTYPE *PFN_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
+       typedef HRESULT (STDAPICALLTYPE *PFN_CloseThemeData)(HTHEME hTheme);
+       typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect);
+       typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeParentBackground)(HWND hwnd, HDC hdc, OPTIONAL RECT* prc);
+
+       HMODULE m_hThemeDLL;
+       HTHEME m_hTheme;
+       PFN_DrawThemeBackground m_pfnDrawThemeBackground;
+       PFN_DrawThemeParentBackground m_pfnDrawThemeParentBackground;
+#endif // !_WTL_NO_AUTO_THEME
+
+// Constructor/destructor
+       CMDICommandBarCtrlImpl() : 
+                       m_wndMDIClient(this, 2), m_bChildMaximized(false), 
+                       m_hWndChildMaximized(NULL), m_hIconChildMaximized(NULL), 
+                       m_nBtnPressed(-1), m_nBtnWasPressed(-1),
+#ifndef _WTL_NO_AUTO_THEME
+                       m_hThemeDLL(NULL), m_hTheme(NULL), m_pfnDrawThemeBackground(NULL), m_pfnDrawThemeParentBackground(NULL), 
+#endif // !_WTL_NO_AUTO_THEME
+                       m_cxyOffset(2),
+                       m_cxIconWidth(16), m_cyIconHeight(16),
+                       m_cxBtnWidth(16), m_cyBtnHeight(14),
+                       m_cxLeft(20), m_cxRight(55)
+       { }
+
+       ~CMDICommandBarCtrlImpl()
+       {
+               if(m_wndMDIClient.IsWindow())
+/*scary!*/                     m_wndMDIClient.UnsubclassWindow();
+       }
+
+// Operations
+       BOOL SetMDIClient(HWND hWndMDIClient)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(::IsWindow(hWndMDIClient));
+               if(!::IsWindow(hWndMDIClient))
+                       return FALSE;
+
+#ifdef _DEBUG
+               // BLOCK: Test if the passed window is MDICLIENT
+               {
+                       LPCTSTR lpszMDIClientClass = _T("MDICLIENT");
+                       const int nNameLen = 9 + 1;   // "MDICLIENT" + NULL
+                       TCHAR szClassName[nNameLen] = { 0 };
+                       ::GetClassName(hWndMDIClient, szClassName, nNameLen);
+                       ATLASSERT(lstrcmpi(szClassName, lpszMDIClientClass) == 0);
+               }
+#endif // _DEBUG
+
+               if(m_wndMDIClient.IsWindow())
+/*scary!*/             m_wndMDIClient.UnsubclassWindow();
+
+               return m_wndMDIClient.SubclassWindow(hWndMDIClient);
+       }
+
+// Message maps
+       typedef CCommandBarCtrlImpl< T, TBase, TWinTraits >   _baseClass;
+       BEGIN_MSG_MAP(CMDICommandBarCtrlImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+#ifndef _WTL_NO_AUTO_THEME
+               MESSAGE_HANDLER(_GetThemeChangedMsg(), OnThemeChanged)
+#endif // !_WTL_NO_AUTO_THEME
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
+               MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
+               MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
+               MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown)
+               MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
+               MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
+               MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClk)
+               MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
+               CHAIN_MSG_MAP(_baseClass)
+       ALT_MSG_MAP(1)   // Parent window messages
+               MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate)
+               CHAIN_MSG_MAP_ALT(_baseClass, 1)
+       ALT_MSG_MAP(2)   // MDI client window messages
+               MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
+               // no chaining needed since this was moved from the base class here
+       ALT_MSG_MAP(3)   // Message hook messages
+               MESSAGE_RANGE_HANDLER(0, 0xFFFF, OnAllHookMessages)
+               CHAIN_MSG_MAP_ALT(_baseClass, 3)
+       END_MSG_MAP()
+
+// Additional MDI message handlers
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               LRESULT lRet = _baseClass::OnCreate(uMsg, wParam, lParam, bHandled);
+               if(lRet == (LRESULT)-1)
+                       return lRet;
+
+#ifndef _WTL_NO_AUTO_THEME
+               // this will fail if theming is not supported
+               m_hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
+               if(m_hThemeDLL != NULL)
+               {
+                       m_pfnDrawThemeBackground = (PFN_DrawThemeBackground)::GetProcAddress(m_hThemeDLL, "DrawThemeBackground");
+                       ATLASSERT(m_pfnDrawThemeBackground != NULL);
+                       if(m_pfnDrawThemeBackground != NULL)
+                       {
+                               T* pT = static_cast<T*>(this);
+                               pT->_OpenThemeData();
+                       }
+                       else
+                       {
+                               ::FreeLibrary(m_hThemeDLL);
+                               m_hThemeDLL = NULL;
+                       }
+                       m_pfnDrawThemeParentBackground = (PFN_DrawThemeParentBackground)::GetProcAddress(m_hThemeDLL, "DrawThemeParentBackground");
+                       ATLASSERT(m_pfnDrawThemeParentBackground != NULL);
+               }
+#endif // !_WTL_NO_AUTO_THEME
+
+               return lRet;
+       }
+
+       LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               LRESULT lRet = _baseClass::OnDestroy(uMsg, wParam, lParam, bHandled);
+
+#ifndef _WTL_NO_AUTO_THEME
+               if(m_hThemeDLL != NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->_CloseThemeData();
+                       ::FreeLibrary(m_hThemeDLL);
+                       m_hThemeDLL = NULL;
+               }
+#endif // !_WTL_NO_AUTO_THEME
+
+               return lRet;
+       }
+
+#ifndef _WTL_NO_AUTO_THEME
+       LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(m_hThemeDLL != NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->_CloseThemeData();
+                       pT->_OpenThemeData();
+               }
+               return 0;
+       }
+#endif // !_WTL_NO_AUTO_THEME
+
+       LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               T* pT = static_cast<T*>(this);
+               pT->_AdjustBtnSize(GET_Y_LPARAM(lParam));
+               return lRet;
+       }
+
+       LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+               if(m_bChildMaximized && (BOOL)wParam)
+               {
+                       LPNCCALCSIZE_PARAMS lpParams = (LPNCCALCSIZE_PARAMS)lParam;
+                       if(m_bLayoutRTL)
+                       {
+                               lpParams->rgrc[0].left += m_cxRight;
+                               lpParams->rgrc[0].right -= m_cxLeft;
+                       }
+                       else
+                       {
+                               lpParams->rgrc[0].left += m_cxLeft;
+                               lpParams->rgrc[0].right -= m_cxRight;
+                       }
+               }
+
+               return lRet;
+       }
+
+       LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+               if(!m_bChildMaximized)
+                       return lRet;
+
+               ATLASSERT(m_hWndChildMaximized != NULL && m_hIconChildMaximized != NULL);
+
+               // get DC and window rectangle
+               CWindowDC dc(m_hWnd);
+               RECT rect;
+               GetWindowRect(&rect);
+               int cxWidth = rect.right - rect.left;
+               int cyHeight = rect.bottom - rect.top;
+
+               // paint left side nonclient background and draw icon
+               ::SetRect(&rect, 0, 0, m_cxLeft, cyHeight);
+#ifndef _WTL_NO_AUTO_THEME
+               if(m_hTheme != NULL)
+               {
+                       if(m_pfnDrawThemeParentBackground != NULL)
+                               m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect);
+                       else
+                               dc.FillRect(&rect, COLOR_WINDOW);
+               }
+               else
+#endif // !_WTL_NO_AUTO_THEME
+               {
+                       if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0)
+                               dc.FillRect(&rect, COLOR_3DFACE);
+                       else
+                               dc.FillRect(&rect, COLOR_MENU);
+               }
+
+               RECT rcIcon = { 0 };
+               T* pT = static_cast<T*>(this);
+               pT->_CalcIconRect(cxWidth, cyHeight, rcIcon);
+               dc.DrawIconEx(rcIcon.left, rcIcon.top, m_hIconChildMaximized, m_cxIconWidth, m_cyIconHeight);
+
+               // paint right side nonclient background
+               ::SetRect(&rect, cxWidth - m_cxRight, 0, cxWidth, cyHeight);
+#ifndef _WTL_NO_AUTO_THEME
+               if(m_hTheme != NULL)
+               {
+                       if(m_pfnDrawThemeParentBackground != NULL)
+                       {
+                               // this is to account for the left non-client area
+                               POINT ptOrg = { 0, 0 };
+                               dc.GetViewportOrg(&ptOrg);
+                               dc.SetViewportOrg(ptOrg.x + m_cxLeft, ptOrg.y);
+                               ::OffsetRect(&rect, -m_cxLeft, 0);
+
+                               m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect);
+
+                               // restore
+                               dc.SetViewportOrg(ptOrg);
+                               ::OffsetRect(&rect, m_cxLeft, 0);
+                       }
+                       else
+                       {
+                               dc.FillRect(&rect, COLOR_3DFACE);
+                       }
+               }
+               else
+#endif // !_WTL_NO_AUTO_THEME
+               {
+                       if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0)
+                               dc.FillRect(&rect, COLOR_3DFACE);
+                       else
+                               dc.FillRect(&rect, COLOR_MENU);
+               }
+
+               // draw buttons
+               RECT arrRect[3] = { 0 };
+               pT->_CalcBtnRects(cxWidth, cyHeight, arrRect);
+               pT->_DrawMDIButton(dc, arrRect, -1);   // draw all buttons
+
+               return lRet;
+       }
+
+       LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               if(m_bChildMaximized)
+               {
+                       RECT rect = { 0 };
+                       GetWindowRect(&rect);
+                       POINT pt = { GET_X_LPARAM(lParam) - rect.left, GET_Y_LPARAM(lParam) - rect.top };
+                       if(m_bLayoutRTL)
+                       {
+                               if((pt.x < m_cxRight) || (pt.x > ((rect.right - rect.left) - m_cxLeft)))
+                                       lRet = HTBORDER;
+                       }
+                       else
+                       {
+                               if((pt.x < m_cxLeft) || (pt.x > ((rect.right - rect.left) - m_cxRight)))
+                                       lRet = HTBORDER;
+                       }
+               }
+               return lRet;
+       }
+
+       LRESULT OnNcLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(!m_bChildMaximized)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               ATLASSERT(_DebugCheckChild());
+
+               POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+               RECT rect = { 0 };
+               GetWindowRect(&rect);
+               pt.x -= rect.left;
+               pt.y -= rect.top;
+
+               RECT rcIcon = { 0 };
+               T* pT = static_cast<T*>(this);
+               pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top, rcIcon, m_bLayoutRTL);
+               RECT arrRect[3] = { 0 };
+               pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL);
+
+               if(::PtInRect(&rcIcon, pt))
+               {
+#ifdef _CMDBAR_EXTRA_TRACE
+                       ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: icon\n"));
+#endif
+#ifndef TPM_VERPOSANIMATION
+                       const UINT TPM_VERPOSANIMATION = 0x1000L;   // Menu animation flag
+#endif
+                       CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized, FALSE);
+                       UINT uRet = (UINT)menu.TrackPopupMenu(TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD |  
+                               (s_bW2K ? TPM_VERPOSANIMATION : 0), m_bLayoutRTL ? rect.right : rect.left, rect.bottom, m_hWndChildMaximized);
+
+                       // eat next message if click is on the same button
+                       ::OffsetRect(&rcIcon, rect.left, rect.top);
+                       MSG msg = { 0 };
+                       if(::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rcIcon, msg.pt))
+                               ::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, PM_REMOVE);
+
+                       if(uRet != 0)
+                               ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uRet, 0L);
+               }
+               else if(::PtInRect(&arrRect[0], pt))
+               {
+#ifdef _CMDBAR_EXTRA_TRACE
+                       ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: close button\n"));
+#endif
+                       m_nBtnWasPressed = m_nBtnPressed = 0;
+               }
+               else if(::PtInRect(&arrRect[1], pt))
+               {
+#ifdef _CMDBAR_EXTRA_TRACE
+                       ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: restore button\n"));
+#endif
+                       m_nBtnWasPressed = m_nBtnPressed = 1;
+               }
+               else if(::PtInRect(&arrRect[2], pt))
+               {
+#ifdef _CMDBAR_EXTRA_TRACE
+                       ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: minimize button\n"));
+#endif
+                       m_nBtnWasPressed = m_nBtnPressed = 2;
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+
+               // draw the button state if it was pressed
+               if(m_nBtnPressed != -1)
+               {
+                       SetCapture();
+                       CWindowDC dc(m_hWnd);
+                       pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect);
+                       pT->_DrawMDIButton(dc, arrRect, m_nBtnPressed);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPressed == -1)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+               ClientToScreen(&pt);
+               RECT rect = { 0 };
+               GetWindowRect(&rect);
+               pt.x -= rect.left;
+               pt.y -= rect.top;
+               RECT arrRect[3] = { 0 };
+               T* pT = static_cast<T*>(this);
+               pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL);
+               int nOldBtnPressed = m_nBtnPressed;
+               m_nBtnPressed = ::PtInRect(&arrRect[m_nBtnWasPressed], pt) ? m_nBtnWasPressed : -1;
+               if(nOldBtnPressed != m_nBtnPressed)
+               {
+                       CWindowDC dc(m_hWnd);
+                       pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect);
+                       pT->_DrawMDIButton(dc, arrRect, (m_nBtnPressed != -1) ? m_nBtnPressed : nOldBtnPressed);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPressed == -1)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               ATLASSERT(_DebugCheckChild());
+
+               POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+               ClientToScreen(&pt);
+               RECT rect = { 0 };
+               GetWindowRect(&rect);
+               pt.x -= rect.left;
+               pt.y -= rect.top;
+
+               int nBtn = m_nBtnWasPressed;
+               ReleaseCapture();
+
+               RECT arrRect[3] = { 0 };
+               T* pT = static_cast<T*>(this);
+               pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL);
+               if(::PtInRect(&arrRect[nBtn], pt))
+               {
+                       switch(nBtn)
+                       {
+                       case 0:         // close
+#ifdef _CMDBAR_EXTRA_TRACE
+                               ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: close button\n"));
+#endif
+                               ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_CLOSE, 0L);
+                               break;
+                       case 1:         // restore
+#ifdef _CMDBAR_EXTRA_TRACE
+                               ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: restore button\n"));
+#endif
+                               ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_RESTORE, 0L);
+                               break;
+                       case 2:         // minimize
+#ifdef _CMDBAR_EXTRA_TRACE
+                               ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: minimize button\n"));
+#endif
+                               ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_MINIMIZE, 0L);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               return 0;
+       }
+
+       LRESULT OnNcLButtonDblClk(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(!m_bChildMaximized || m_nBtnWasPressed != -1)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               ATLASSERT(_DebugCheckChild());
+
+               POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+               RECT rect = { 0 };
+               GetWindowRect(&rect);
+               pt.x -= rect.left;
+               pt.y -= rect.top;
+
+               RECT rcIcon = { 0 };
+               T* pT = static_cast<T*>(this);
+               pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top, rcIcon, m_bLayoutRTL);
+               RECT arrRect[3] = { 0 };
+               pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL);
+
+               if(::PtInRect(&rcIcon, pt))
+               {
+                       CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized, FALSE);
+                       UINT uDefID = menu.GetMenuDefaultItem();
+                       if(uDefID == (UINT)-1)
+                               uDefID = SC_CLOSE;
+                       ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uDefID, 0L);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_bChildMaximized)
+               {
+                       if(m_nBtnPressed != -1)
+                       {
+                               ATLASSERT(m_nBtnPressed == m_nBtnWasPressed);   // must be
+                               m_nBtnPressed = -1;
+                               RECT rect = { 0 };
+                               GetWindowRect(&rect);
+                               RECT arrRect[3] = { 0 };
+                               T* pT = static_cast<T*>(this);
+                               pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect);
+                               CWindowDC dc(m_hWnd);
+                               pT->_DrawMDIButton(dc, arrRect, m_nBtnWasPressed);
+                       }
+                       m_nBtnWasPressed = -1;
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+               return 0;
+       }
+
+// Parent window message handlers
+       LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               m_bParentActive = (LOWORD(wParam) != WA_INACTIVE);
+               RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW);
+               bHandled = FALSE;
+               return 1;
+       }
+
+// MDI client window message handlers
+       LRESULT OnMDISetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               m_wndMDIClient.DefWindowProc(uMsg, NULL, lParam);
+               HMENU hOldMenu = GetMenu();
+               BOOL bRet = AttachMenu((HMENU)wParam);
+               bRet;   // avoid level 4 warning
+               ATLASSERT(bRet);
+
+#if (_WIN32_IE >= 0x0400)
+               T* pT = static_cast<T*>(this);
+               pT->UpdateRebarBandIdealSize();
+#endif // (_WIN32_IE >= 0x0400)
+
+               return (LRESULT)hOldMenu;
+       }
+
+// All messages from the message hook
+       LRESULT OnAllHookMessages(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->_ProcessAllHookMessages(uMsg, wParam, lParam);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+// Overrideables
+       // override this to provide different ideal size
+       void UpdateRebarBandIdealSize()
+       {
+               // assuming we are in a rebar, change ideal size to our size
+               // we hope that if we are not in a rebar, nCount will be 0
+               int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L);
+               for(int i = 0; i < nCount; i++)
+               {
+                       REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE };
+                       ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
+                       if(rbi.hwndChild == m_hWnd)
+                       {
+                               rbi.fMask = RBBIM_IDEALSIZE;
+                               rbi.cxIdeal = m_bChildMaximized ? m_cxLeft + m_cxRight : 0;
+                               int nBtnCount = GetButtonCount();
+                               if(nBtnCount > 0)
+                               {
+                                       RECT rect = { 0 };
+                                       GetItemRect(nBtnCount - 1, &rect);
+                                       rbi.cxIdeal += rect.right;
+                               }
+                               ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
+                               break;
+                       }
+               }
+       }
+
+       // all hook messages - check for the maximized MDI child window change
+       void _ProcessAllHookMessages(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/)
+       {
+               if(uMsg == WM_MDIGETACTIVE || uMsg == WM_MDISETMENU)
+                       return;
+
+               BOOL bMaximized = FALSE;
+               HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
+               bool bMaxOld = m_bChildMaximized;
+               m_bChildMaximized = (hWndChild != NULL && bMaximized);
+               HICON hIconOld = m_hIconChildMaximized;
+
+               if(m_bChildMaximized)
+               {
+                       if(m_hWndChildMaximized != hWndChild)
+                       {
+                               ATL::CWindow wnd = m_hWndChildMaximized = hWndChild;
+                               m_hIconChildMaximized = wnd.GetIcon(FALSE);
+                               if(m_hIconChildMaximized == NULL)
+                               {
+                                       m_hIconChildMaximized = wnd.GetIcon(TRUE);
+                                       if(m_hIconChildMaximized == NULL)
+                                       {
+                                               // no icon set with WM_SETICON, get the class one
+// need conditional code because types don't match in winuser.h
+#ifdef _WIN64
+                                               m_hIconChildMaximized = (HICON)::GetClassLongPtr(wnd, GCLP_HICONSM);
+#else
+                                               m_hIconChildMaximized = (HICON)LongToHandle(::GetClassLongPtr(wnd, GCLP_HICONSM));
+#endif
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       m_hWndChildMaximized = NULL;
+                       m_hIconChildMaximized = NULL;
+               }
+
+               if(bMaxOld != m_bChildMaximized)
+               {
+#ifdef _CMDBAR_EXTRA_TRACE
+                       ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - All messages hook change: m_bChildMaximized = %s\n"), m_bChildMaximized ? "true" : "false");
+#endif
+                       // assuming we are in a rebar, change our size to accomodate new state
+                       // we hope that if we are not in a rebar, nCount will be 0
+                       int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L);
+                       int cxDiff = (m_bChildMaximized ? 1 : -1) * (m_cxLeft + m_cxRight);
+                       for(int i = 0; i < nCount; i++)
+                       {
+#if (_WIN32_IE >= 0x0500)
+                               REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE };
+                               ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
+                               if(rbi.hwndChild == m_hWnd)
+                               {
+                                       if((rbi.fStyle & RBBS_USECHEVRON) != 0)
+                                       {
+                                               rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
+                                               rbi.cxMinChild += cxDiff;
+                                               rbi.cxIdeal += cxDiff;
+                                               ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
+                                       }
+                                       break;
+                               }
+#elif (_WIN32_IE >= 0x0400)
+                               REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE };
+                               ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
+                               if(rbi.hwndChild == m_hWnd)
+                               {
+                                       rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
+                                       rbi.cxMinChild += cxDiff;
+                                       rbi.cxIdeal += cxDiff;
+                                       ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
+                                       break;
+                               }
+#else // (_WIN32_IE < 0x0400)
+                               REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE };
+                               ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
+                               if(rbi.hwndChild == m_hWnd)
+                               {
+                                       rbi.fMask = RBBIM_CHILDSIZE;
+                                       rbi.cxMinChild += cxDiff;
+                                       ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
+                                       break;
+                               }
+#endif // (_WIN32_IE < 0x0400)
+                       }
+               }
+
+               if(bMaxOld != m_bChildMaximized || hIconOld != m_hIconChildMaximized)
+               {
+                       // force size change and redraw everything
+                       RECT rect = { 0 };
+                       GetWindowRect(&rect);
+                       ::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2);
+                       SetRedraw(FALSE);
+                       SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE);
+                       SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
+                       SetRedraw(TRUE);
+                       RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
+               }
+       }
+
+// Implementation
+       void GetSystemSettings()
+       {
+#ifdef _CMDBAR_EXTRA_TRACE
+               ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - GetSystemSettings\n"));
+#endif
+               _baseClass::GetSystemSettings();
+
+               NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
+               BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+               ATLASSERT(bRet);
+               if(bRet)
+               {
+                       m_cxIconWidth = ::GetSystemMetrics(SM_CXSMICON);
+                       m_cyIconHeight = ::GetSystemMetrics(SM_CYSMICON);
+                       m_cxLeft = m_cxIconWidth;
+
+#ifndef _WTL_NO_AUTO_THEME
+                       if(m_hTheme != NULL)
+                       {
+                               m_cxBtnWidth = info.iCaptionWidth - 2 * m_cxyOffset;
+                               m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyOffset;
+                               m_cxRight = 3 * m_cxBtnWidth;
+                       }
+                       else
+#endif // !_WTL_NO_AUTO_THEME
+                       {
+                               m_cxBtnWidth = info.iCaptionWidth - m_cxyOffset;
+                               m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyOffset;
+                               m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset;
+                       }
+               }
+
+               RECT rect = { 0 };
+               GetClientRect(&rect);
+               T* pT = static_cast<T*>(this);
+               pT->_AdjustBtnSize(rect.bottom);
+       }
+
+       void _AdjustBtnSize(int cyHeight)
+       {
+               if(cyHeight > 1 && m_cyBtnHeight > cyHeight)
+               {
+#ifndef _WTL_NO_AUTO_THEME
+                       if(m_hTheme != NULL)
+                       {
+                               m_cyBtnHeight = cyHeight;
+                               m_cxBtnWidth = cyHeight;
+                               m_cxRight = 3 * m_cxBtnWidth;
+                       }
+                       else
+#endif // !_WTL_NO_AUTO_THEME
+                       {
+                               m_cyBtnHeight = cyHeight;
+                               m_cxBtnWidth = cyHeight + m_cxyOffset;
+                               m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset;
+                       }
+               }
+       }
+
+       void _CalcIconRect(int cxWidth, int cyHeight, RECT& rect, bool bInvertX = false) const
+       {
+               int xStart = (m_cxLeft - m_cxIconWidth) / 2;
+               if(xStart < 0)
+                       xStart = 0;
+               int yStart = (cyHeight - m_cyIconHeight) / 2;
+               if(yStart < 0)
+                       yStart = 0;
+
+               if(bInvertX)
+                       ::SetRect(&rect, cxWidth - (xStart + m_cxBtnWidth), yStart, cxWidth - xStart, yStart + m_cyBtnHeight);
+               else
+                       ::SetRect(&rect, xStart, yStart, xStart + m_cxBtnWidth, yStart + m_cyBtnHeight);
+       }
+
+       void _CalcBtnRects(int cxWidth, int cyHeight, RECT arrRect[3], bool bInvertX = false) const
+       {
+               int yStart = (cyHeight - m_cyBtnHeight) / 2;
+               if(yStart < 0)
+                       yStart = 0;
+
+               RECT rcBtn = { cxWidth - m_cxBtnWidth, yStart, cxWidth, yStart + m_cyBtnHeight };
+               int nDirection = -1;
+               if(bInvertX)
+               {
+                       ::SetRect(&rcBtn, 0, yStart, m_cxBtnWidth, yStart + m_cyBtnHeight);
+                       nDirection = 1;
+               }
+
+               arrRect[0] = rcBtn;
+#ifndef _WTL_NO_AUTO_THEME
+               if(m_hTheme != NULL)
+                       ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0);
+               else
+#endif // !_WTL_NO_AUTO_THEME
+                       ::OffsetRect(&rcBtn, nDirection * (m_cxBtnWidth + m_cxyOffset), 0);
+               arrRect[1] = rcBtn;
+               ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0);
+               arrRect[2] = rcBtn;
+       }
+
+       void _DrawMDIButton(CWindowDC& dc, LPRECT pRects, int nBtn)
+       {
+#ifndef _WTL_NO_AUTO_THEME
+               if(m_hTheme != NULL)
+               {
+#ifndef TMSCHEMA_H
+                       const int WP_MDICLOSEBUTTON = 20;
+                       const int CBS_NORMAL = 1;
+                       const int CBS_PUSHED = 3;
+                       const int CBS_DISABLED = 4;
+                       const int WP_MDIRESTOREBUTTON = 22;
+                       const int RBS_NORMAL = 1;
+                       const int RBS_PUSHED = 3;
+                       const int RBS_DISABLED = 4;
+                       const int WP_MDIMINBUTTON = 16;
+                       const int MINBS_NORMAL = 1;
+                       const int MINBS_PUSHED = 3;
+                       const int MINBS_DISABLED = 4;
+#endif // TMSCHEMA_H
+                       if(nBtn == -1 || nBtn == 0)
+                               m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDICLOSEBUTTON, m_bParentActive ? ((m_nBtnPressed == 0) ? CBS_PUSHED : CBS_NORMAL) : CBS_DISABLED, &pRects[0], NULL);
+                       if(nBtn == -1 || nBtn == 1)
+                               m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIRESTOREBUTTON, m_bParentActive ? ((m_nBtnPressed == 1) ? RBS_PUSHED : RBS_NORMAL) : RBS_DISABLED, &pRects[1], NULL);
+                       if(nBtn == -1 || nBtn == 2)
+                               m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIMINBUTTON, m_bParentActive ? ((m_nBtnPressed == 2) ? MINBS_PUSHED : MINBS_NORMAL) : MINBS_DISABLED, &pRects[2], NULL);
+               }
+               else
+#endif // !_WTL_NO_AUTO_THEME
+               {
+                       if(nBtn == -1 || nBtn == 0)
+                               dc.DrawFrameControl(&pRects[0], DFC_CAPTION, DFCS_CAPTIONCLOSE | ((m_nBtnPressed == 0) ? DFCS_PUSHED : 0));
+                       if(nBtn == -1 || nBtn == 1)
+                               dc.DrawFrameControl(&pRects[1], DFC_CAPTION, DFCS_CAPTIONRESTORE | ((m_nBtnPressed == 1) ? DFCS_PUSHED : 0));
+                       if(nBtn == -1 || nBtn == 2)
+                               dc.DrawFrameControl(&pRects[2], DFC_CAPTION, DFCS_CAPTIONMIN | ((m_nBtnPressed == 2) ? DFCS_PUSHED : 0));
+               }
+       }
+
+#ifndef _WTL_NO_AUTO_THEME
+       static UINT _GetThemeChangedMsg()
+       {
+#ifndef WM_THEMECHANGED
+               static const UINT WM_THEMECHANGED = 0x031A;
+#endif // !WM_THEMECHANGED
+               return WM_THEMECHANGED;
+       }
+
+       void _OpenThemeData()
+       {
+               ATLASSERT(m_hThemeDLL != NULL);
+
+               PFN_OpenThemeData pfnOpenThemeData = (PFN_OpenThemeData)::GetProcAddress(m_hThemeDLL, "OpenThemeData");
+               ATLASSERT(pfnOpenThemeData != NULL);
+               if(pfnOpenThemeData != NULL)
+                       m_hTheme = pfnOpenThemeData(m_hWnd, L"Window");
+       }
+
+       void _CloseThemeData()
+       {
+               ATLASSERT(m_hThemeDLL != NULL);
+
+               if(m_hTheme == NULL)
+                       return;   // nothing to do
+
+               PFN_CloseThemeData pfnCloseThemeData = (PFN_CloseThemeData)::GetProcAddress(m_hThemeDLL, "CloseThemeData");
+               ATLASSERT(pfnCloseThemeData != NULL);
+               if(pfnCloseThemeData != NULL)
+               {
+                       pfnCloseThemeData(m_hTheme);
+                       m_hTheme = NULL;
+               }
+       }
+#endif // !_WTL_NO_AUTO_THEME
+
+       bool _DebugCheckChild()
+       {
+#ifdef _DEBUG
+               BOOL bMaximized = FALSE;
+               HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
+               return (bMaximized && hWndChild == m_hWndChildMaximized);
+#else // !_DEBUG
+               return true;
+#endif // !_DEBUG
+       }
+};
+
+class CMDICommandBarCtrl : public CMDICommandBarCtrlImpl<CMDICommandBarCtrl>
+{
+public:
+       DECLARE_WND_SUPERCLASS(_T("WTL_MDICommandBar"), GetWndClassName())
+};
+
+}; // namespace WTL
+
+#endif // __ATLCTRLW_H__
diff --git a/include/WTL/Include/atlctrlx.h b/include/WTL/Include/atlctrlx.h
new file mode 100644 (file)
index 0000000..4861b9f
--- /dev/null
@@ -0,0 +1,4827 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLCTRLX_H__
+#define __ATLCTRLX_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlctrlx.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLCTRLS_H__
+       #error atlctrlx.h requires atlctrls.h to be included first
+#endif
+
+#ifndef WM_UPDATEUISTATE
+  #define WM_UPDATEUISTATE                0x0128
+#endif // !WM_UPDATEUISTATE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CBitmapButtonImpl<T, TBase, TWinTraits>
+// CBitmapButton
+// CCheckListViewCtrlImpl<T, TBase, TWinTraits>
+// CCheckListViewCtrl
+// CHyperLinkImpl<T, TBase, TWinTraits>
+// CHyperLink
+// CWaitCursor
+// CCustomWaitCursor
+// CMultiPaneStatusBarCtrlImpl<T, TBase>
+// CMultiPaneStatusBarCtrl
+// CPaneContainerImpl<T, TBase, TWinTraits>
+// CPaneContainer
+// CSortListViewImpl<T>
+// CSortListViewCtrlImpl<T, TBase, TWinTraits>
+// CSortListViewCtrl
+// CTabViewImpl<T, TBase, TWinTraits>
+// CTabView
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CBitmapButton - bitmap button implementation
+
+#ifndef _WIN32_WCE
+
+// bitmap button extended styles
+#define BMPBTN_HOVER           0x00000001
+#define BMPBTN_AUTO3D_SINGLE   0x00000002
+#define BMPBTN_AUTO3D_DOUBLE   0x00000004
+#define BMPBTN_AUTOSIZE                0x00000008
+#define BMPBTN_SHAREIMAGELISTS 0x00000010
+#define BMPBTN_AUTOFIRE                0x00000020
+
+template <class T, class TBase = CButton, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CBitmapButtonImpl : public ATL::CWindowImpl< T, TBase, TWinTraits>
+{
+public:
+       DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
+
+       enum
+       {
+               _nImageNormal = 0,
+               _nImagePushed,
+               _nImageFocusOrHover,
+               _nImageDisabled,
+
+               _nImageCount = 4,
+       };
+
+       enum
+       {
+               ID_TIMER_FIRST = 1000,
+               ID_TIMER_REPEAT = 1001
+       };
+
+       // Bitmap button specific extended styles
+       DWORD m_dwExtendedStyle;
+
+       CImageList m_ImageList;
+       int m_nImage[_nImageCount];
+
+       CToolTipCtrl m_tip;
+       LPTSTR m_lpstrToolTipText;
+
+       // Internal states
+       unsigned m_fMouseOver:1;
+       unsigned m_fFocus:1;
+       unsigned m_fPressed:1;
+
+
+// Constructor/Destructor
+       CBitmapButtonImpl(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) : 
+                       m_ImageList(hImageList), m_dwExtendedStyle(dwExtendedStyle), 
+                       m_lpstrToolTipText(NULL),
+                       m_fMouseOver(0), m_fFocus(0), m_fPressed(0)
+       {
+               m_nImage[_nImageNormal] = -1;
+               m_nImage[_nImagePushed] = -1;
+               m_nImage[_nImageFocusOrHover] = -1;
+               m_nImage[_nImageDisabled] = -1;
+       }
+
+       ~CBitmapButtonImpl()
+       {
+               if((m_dwExtendedStyle & BMPBTN_SHAREIMAGELISTS) == 0)
+                       m_ImageList.Destroy();
+               delete [] m_lpstrToolTipText;
+       }
+
+       // overridden to provide proper initialization
+       BOOL SubclassWindow(HWND hWnd)
+       {
+#if (_MSC_VER >= 1300)
+               BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd);
+#else // !(_MSC_VER >= 1300)
+               typedef ATL::CWindowImpl< T, TBase, TWinTraits>   _baseClass;
+               BOOL bRet = _baseClass::SubclassWindow(hWnd);
+#endif // !(_MSC_VER >= 1300)
+               if(bRet)
+                       Init();
+               return bRet;
+       }
+
+// Attributes
+       DWORD GetBitmapButtonExtendedStyle() const
+       {
+               return m_dwExtendedStyle;
+       }
+
+       DWORD SetBitmapButtonExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
+       {
+               DWORD dwPrevStyle = m_dwExtendedStyle;
+               if(dwMask == 0)
+                       m_dwExtendedStyle = dwExtendedStyle;
+               else
+                       m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
+               return dwPrevStyle;
+       }
+
+       HIMAGELIST GetImageList() const
+       {
+               return m_ImageList;
+       }
+
+       HIMAGELIST SetImageList(HIMAGELIST hImageList)
+       {
+               HIMAGELIST hImageListPrev = m_ImageList;
+               m_ImageList = hImageList;
+               if((m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0 && ::IsWindow(m_hWnd))
+                       SizeToImage();
+               return hImageListPrev;
+       }
+
+       int GetToolTipTextLength() const
+       {
+               return (m_lpstrToolTipText == NULL) ? -1 : lstrlen(m_lpstrToolTipText);
+       }
+
+       bool GetToolTipText(LPTSTR lpstrText, int nLength) const
+       {
+               ATLASSERT(lpstrText != NULL);
+               if(m_lpstrToolTipText == NULL)
+                       return false;
+
+               errno_t nRet = SecureHelper::strncpy_x(lpstrText, nLength, m_lpstrToolTipText, _TRUNCATE);
+
+               return (nRet == 0 || nRet == STRUNCATE);
+       }
+
+       bool SetToolTipText(LPCTSTR lpstrText)
+       {
+               if(m_lpstrToolTipText != NULL)
+               {
+                       delete [] m_lpstrToolTipText;
+                       m_lpstrToolTipText = NULL;
+               }
+
+               if(lpstrText == NULL)
+               {
+                       if(m_tip.IsWindow())
+                               m_tip.Activate(FALSE);
+                       return true;
+               }
+
+               int cchLen = lstrlen(lpstrText) + 1;
+               ATLTRY(m_lpstrToolTipText = new TCHAR[cchLen]);
+               if(m_lpstrToolTipText == NULL)
+                       return false;
+
+               SecureHelper::strcpy_x(m_lpstrToolTipText, cchLen, lpstrText);
+               if(m_tip.IsWindow())
+               {
+                       m_tip.Activate(TRUE);
+                       m_tip.AddTool(m_hWnd, m_lpstrToolTipText);
+               }
+
+               return true;
+       }
+
+// Operations
+       void SetImages(int nNormal, int nPushed = -1, int nFocusOrHover = -1, int nDisabled = -1)
+       {
+               if(nNormal != -1)
+                       m_nImage[_nImageNormal] = nNormal;
+               if(nPushed != -1)
+                       m_nImage[_nImagePushed] = nPushed;
+               if(nFocusOrHover != -1)
+                       m_nImage[_nImageFocusOrHover] = nFocusOrHover;
+               if(nDisabled != -1)
+                       m_nImage[_nImageDisabled] = nDisabled;
+       }
+
+       BOOL SizeToImage()
+       {
+               ATLASSERT(::IsWindow(m_hWnd) && m_ImageList.m_hImageList != NULL);
+               int cx = 0;
+               int cy = 0;
+               if(!m_ImageList.GetIconSize(cx, cy))
+                       return FALSE;
+               return ResizeClient(cx, cy);
+       }
+
+// Overrideables
+       void DoPaint(CDCHandle dc)
+       {
+               ATLASSERT(m_ImageList.m_hImageList != NULL);   // image list must be set
+               ATLASSERT(m_nImage[0] != -1);                  // main bitmap must be set
+
+               // set bitmap according to the current button state
+               int nImage = -1;
+               bool bHover = IsHoverMode();
+               if(!IsWindowEnabled())
+                       nImage = m_nImage[_nImageDisabled];
+               else if(m_fPressed == 1)
+                       nImage = m_nImage[_nImagePushed];
+               else if((!bHover && m_fFocus == 1) || (bHover && m_fMouseOver == 1))
+                       nImage = m_nImage[_nImageFocusOrHover];
+               if(nImage == -1)   // not there, use default one
+                       nImage = m_nImage[_nImageNormal];
+
+               // draw the button image
+               int xyPos = 0;
+               if((m_fPressed == 1) && ((m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0) && (m_nImage[_nImagePushed] == -1))
+                       xyPos = 1;
+               m_ImageList.Draw(dc, nImage, xyPos, xyPos, ILD_NORMAL);
+
+               // draw 3D border if required
+               if((m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0)
+               {
+                       RECT rect;
+                       GetClientRect(&rect);
+
+                       if(m_fPressed == 1)
+                               dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_SUNKENOUTER : EDGE_SUNKEN, BF_RECT);
+                       else if(!bHover || m_fMouseOver == 1)
+                               dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_RAISEDINNER : EDGE_RAISED, BF_RECT);
+
+                       if(!bHover && m_fFocus == 1)
+                       {
+                               ::InflateRect(&rect, -2 * ::GetSystemMetrics(SM_CXEDGE), -2 * ::GetSystemMetrics(SM_CYEDGE));
+                               dc.DrawFocusRect(&rect);
+                       }
+               }
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CBitmapButtonImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+               MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
+               MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+               MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)
+               MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
+               MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
+               MESSAGE_HANDLER(WM_ENABLE, OnEnable)
+               MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
+               MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
+               MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
+               MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
+               MESSAGE_HANDLER(WM_TIMER, OnTimer)
+               MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               Init();
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_tip.IsWindow())
+               {
+                       m_tip.DestroyWindow();
+                       m_tip.m_hWnd = NULL;
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               MSG msg = { m_hWnd, uMsg, wParam, lParam };
+               if(m_tip.IsWindow())
+                       m_tip.RelayEvent(&msg);
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;   // no background needed
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               if(wParam != NULL)
+               {
+                       pT->DoPaint((HDC)wParam);
+               }
+               else
+               {
+                       CPaintDC dc(m_hWnd);
+                       pT->DoPaint(dc.m_hDC);
+               }
+               return 0;
+       }
+
+       LRESULT OnFocus(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               m_fFocus = (uMsg == WM_SETFOCUS) ? 1 : 0;
+               Invalidate();
+               UpdateWindow();
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = 0;
+               if(IsHoverMode())
+                       SetCapture();
+               else
+                       lRet = DefWindowProc(uMsg, wParam, lParam);
+               if(::GetCapture() == m_hWnd)
+               {
+                       m_fPressed = 1;
+                       Invalidate();
+                       UpdateWindow();
+               }
+               if((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0)
+               {
+                       int nElapse = 250;
+                       int nDelay = 0;
+                       if(::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &nDelay, 0))
+                               nElapse += nDelay * 250;   // all milli-seconds
+                       SetTimer(ID_TIMER_FIRST, nElapse);
+               }
+               return lRet;
+       }
+
+       LRESULT OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = 0;
+               if(!IsHoverMode())
+                       lRet = DefWindowProc(uMsg, wParam, lParam);
+               if(::GetCapture() != m_hWnd)
+                       SetCapture();
+               if(m_fPressed == 0)
+               {
+                       m_fPressed = 1;
+                       Invalidate();
+                       UpdateWindow();
+               }
+               return lRet;
+       }
+
+       LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = 0;
+               bool bHover = IsHoverMode();
+               if(!bHover)
+                       lRet = DefWindowProc(uMsg, wParam, lParam);
+               if(::GetCapture() == m_hWnd)
+               {
+                       if(bHover && m_fPressed == 1)
+                               ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
+                       ::ReleaseCapture();
+               }
+               return lRet;
+       }
+
+       LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_fPressed == 1)
+               {
+                       m_fPressed = 0;
+                       Invalidate();
+                       UpdateWindow();
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               Invalidate();
+               UpdateWindow();
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(::GetCapture() == m_hWnd)
+               {
+                       POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+                       ClientToScreen(&ptCursor);
+                       RECT rect = { 0 };
+                       GetWindowRect(&rect);
+                       unsigned int uPressed = ::PtInRect(&rect, ptCursor) ? 1 : 0;
+                       if(m_fPressed != uPressed)
+                       {
+                               m_fPressed = uPressed;
+                               Invalidate();
+                               UpdateWindow();
+                       }
+               }
+               else if(IsHoverMode() && m_fMouseOver == 0)
+               {
+                       m_fMouseOver = 1;
+                       Invalidate();
+                       UpdateWindow();
+                       StartTrackMouseLeave();
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(m_fMouseOver == 1)
+               {
+                       m_fMouseOver = 0;
+                       Invalidate();
+                       UpdateWindow();
+               }
+               return 0;
+       }
+
+       LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(wParam == VK_SPACE && IsHoverMode())
+                       return 0;   // ignore if in hover mode
+               if(wParam == VK_SPACE && m_fPressed == 0)
+               {
+                       m_fPressed = 1;
+                       Invalidate();
+                       UpdateWindow();
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(wParam == VK_SPACE && IsHoverMode())
+                       return 0;   // ignore if in hover mode
+               if(wParam == VK_SPACE && m_fPressed == 1)
+               {
+                       m_fPressed = 0;
+                       Invalidate();
+                       UpdateWindow();
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               ATLASSERT((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0);
+               switch(wParam)   // timer ID
+               {
+               case ID_TIMER_FIRST:
+                       KillTimer(ID_TIMER_FIRST);
+                       if(m_fPressed == 1)
+                       {
+                               ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
+                               int nElapse = 250;
+                               int nRepeat = 40;
+                               if(::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &nRepeat, 0))
+                                       nElapse = 10000 / (10 * nRepeat + 25);   // milli-seconds, approximated
+                               SetTimer(ID_TIMER_REPEAT, nElapse);
+                       }
+                       break;
+               case ID_TIMER_REPEAT:
+                       if(m_fPressed == 1)
+                               ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
+                       else if(::GetCapture() != m_hWnd)
+                               KillTimer(ID_TIMER_REPEAT);
+                       break;
+               default:        // not our timer
+                       break;
+               }
+               return 0;
+       }
+
+       LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // If the control is subclassed or superclassed, this message can cause
+               // repainting without WM_PAINT. We don't use this state, so just do nothing.
+               return 0;
+       }
+
+// Implementation
+       void Init()
+       {
+               // We need this style to prevent Windows from painting the button
+               ModifyStyle(0, BS_OWNERDRAW);
+
+               // create a tool tip
+               m_tip.Create(m_hWnd);
+               ATLASSERT(m_tip.IsWindow());
+               if(m_tip.IsWindow() && m_lpstrToolTipText != NULL)
+               {
+                       m_tip.Activate(TRUE);
+                       m_tip.AddTool(m_hWnd, m_lpstrToolTipText);
+               }
+
+               if(m_ImageList.m_hImageList != NULL && (m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0)
+                       SizeToImage();
+       }
+
+       BOOL StartTrackMouseLeave()
+       {
+               TRACKMOUSEEVENT tme = { 0 };
+               tme.cbSize = sizeof(tme);
+               tme.dwFlags = TME_LEAVE;
+               tme.hwndTrack = m_hWnd;
+               return _TrackMouseEvent(&tme);
+       }
+
+       bool IsHoverMode() const
+       {
+               return ((m_dwExtendedStyle & BMPBTN_HOVER) != 0);
+       }
+};
+
+
+class CBitmapButton : public CBitmapButtonImpl<CBitmapButton>
+{
+public:
+       DECLARE_WND_SUPERCLASS(_T("WTL_BitmapButton"), GetWndClassName())
+
+       CBitmapButton(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) : 
+               CBitmapButtonImpl<CBitmapButton>(dwExtendedStyle, hImageList)
+       { }
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CCheckListCtrlView - list view control with check boxes
+
+template <DWORD t_dwStyle, DWORD t_dwExStyle, DWORD t_dwExListViewStyle>
+class CCheckListViewCtrlImplTraits
+{
+public:
+       static DWORD GetWndStyle(DWORD dwStyle)
+       {
+               return (dwStyle == 0) ? t_dwStyle : dwStyle;
+       }
+
+       static DWORD GetWndExStyle(DWORD dwExStyle)
+       {
+               return (dwExStyle == 0) ? t_dwExStyle : dwExStyle;
+       }
+
+       static DWORD GetExtendedLVStyle()
+       {
+               return t_dwExListViewStyle;
+       }
+};
+
+typedef CCheckListViewCtrlImplTraits<WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT>   CCheckListViewCtrlTraits;
+
+template <class T, class TBase = CListViewCtrl, class TWinTraits = CCheckListViewCtrlTraits>
+class ATL_NO_VTABLE CCheckListViewCtrlImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>
+{
+public:
+       DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
+
+// Attributes
+       static DWORD GetExtendedLVStyle()
+       {
+               return TWinTraits::GetExtendedLVStyle();
+       }
+
+// Operations
+       BOOL SubclassWindow(HWND hWnd)
+       {
+#if (_MSC_VER >= 1300)
+               BOOL bRet = ATL::CWindowImplBaseT< TBase, TWinTraits>::SubclassWindow(hWnd);
+#else // !(_MSC_VER >= 1300)
+               typedef ATL::CWindowImplBaseT< TBase, TWinTraits>   _baseClass;
+               BOOL bRet = _baseClass::SubclassWindow(hWnd);
+#endif // !(_MSC_VER >= 1300)
+               if(bRet)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT;
+                       ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0);
+                       SetExtendedListViewStyle(pT->GetExtendedLVStyle());
+               }
+               return bRet;
+       }
+
+       void CheckSelectedItems(int nCurrItem)
+       {
+               // first check if this item is selected
+               LVITEM lvi = { 0 };
+               lvi.iItem = nCurrItem;
+               lvi.iSubItem = 0;
+               lvi.mask = LVIF_STATE;
+               lvi.stateMask = LVIS_SELECTED;
+               GetItem(&lvi);
+               // if item is not selected, don't do anything
+               if(!(lvi.state & LVIS_SELECTED))
+                       return;
+               // new check state will be reverse of the current state,
+               BOOL bCheck = !GetCheckState(nCurrItem);
+               int nItem = -1;
+               int nOldItem = -1;
+               while((nItem = GetNextItem(nOldItem, LVNI_SELECTED)) != -1)
+               {
+                       if(nItem != nCurrItem)
+                               SetCheckState(nItem, bCheck);
+                       nOldItem = nItem;
+               }
+       }
+
+// Implementation
+       BEGIN_MSG_MAP(CCheckListViewCtrlImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+               MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDown)
+               MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               // first let list view control initialize everything
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               T* pT = static_cast<T*>(this);
+               pT;
+               ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0);
+               SetExtendedListViewStyle(pT->GetExtendedLVStyle());
+               return lRet;
+       }
+
+       LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               POINT ptMsg = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+               LVHITTESTINFO lvh = { 0 };
+               lvh.pt = ptMsg;
+               if(HitTest(&lvh) != -1 && lvh.flags == LVHT_ONITEMSTATEICON && ::GetKeyState(VK_CONTROL) >= 0)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->CheckSelectedItems(lvh.iItem);
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(wParam == VK_SPACE)
+               {
+                       int nCurrItem = GetNextItem(-1, LVNI_FOCUSED);
+                       if(nCurrItem != -1  && ::GetKeyState(VK_CONTROL) >= 0)
+                       {
+                               T* pT = static_cast<T*>(this);
+                               pT->CheckSelectedItems(nCurrItem);
+                       }
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+};
+
+class CCheckListViewCtrl : public CCheckListViewCtrlImpl<CCheckListViewCtrl>
+{
+public:
+       DECLARE_WND_SUPERCLASS(_T("WTL_CheckListView"), GetWndClassName())
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CHyperLink - hyper link control implementation
+
+#if (WINVER < 0x0500) && !defined(_WIN32_WCE)
+__declspec(selectany) struct
+{
+       enum { cxWidth = 32, cyHeight = 32 };
+       int xHotSpot;
+       int yHotSpot;
+       unsigned char arrANDPlane[cxWidth * cyHeight / 8];
+       unsigned char arrXORPlane[cxWidth * cyHeight / 8];
+} _AtlHyperLink_CursorData = 
+{
+       5, 0, 
+       {
+               0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 
+               0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 
+               0xF0, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 
+               0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 
+               0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 
+               0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+       },
+       {
+               0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 
+               0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xD8, 0x00, 0x00, 
+               0x06, 0xDA, 0x00, 0x00, 0x06, 0xDB, 0x00, 0x00, 0x67, 0xFB, 0x00, 0x00, 0x77, 0xFF, 0x00, 0x00, 
+               0x37, 0xFF, 0x00, 0x00, 0x17, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 
+               0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 
+               0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       }
+};
+#endif // (WINVER < 0x0500) && !defined(_WIN32_WCE)
+
+#define HLINK_UNDERLINED      0x00000000
+#define HLINK_NOTUNDERLINED   0x00000001
+#define HLINK_UNDERLINEHOVER  0x00000002
+#define HLINK_COMMANDBUTTON   0x00000004
+#define HLINK_NOTIFYBUTTON    0x0000000C
+#define HLINK_USETAGS         0x00000010
+#define HLINK_USETAGSBOLD     0x00000030
+#define HLINK_NOTOOLTIP       0x00000040
+
+// Notes:
+// - HLINK_USETAGS and HLINK_USETAGSBOLD are always left-aligned
+// - When HLINK_USETAGSBOLD is used, the underlined styles will be ignored
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CHyperLinkImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >
+{
+public:
+       LPTSTR m_lpstrLabel;
+       LPTSTR m_lpstrHyperLink;
+
+       HCURSOR m_hCursor;
+       HFONT m_hFont;
+       HFONT m_hFontNormal;
+
+       RECT m_rcLink;
+#ifndef _WIN32_WCE
+       CToolTipCtrl m_tip;
+#endif // !_WIN32_WCE
+
+       COLORREF m_clrLink;
+       COLORREF m_clrVisited;
+
+       DWORD m_dwExtendedStyle;   // Hyper Link specific extended styles
+
+       bool m_bPaintLabel:1;
+       bool m_bVisited:1;
+       bool m_bHover:1;
+       bool m_bInternalLinkFont:1;
+
+
+// Constructor/Destructor
+       CHyperLinkImpl(DWORD dwExtendedStyle = HLINK_UNDERLINED) : 
+                       m_lpstrLabel(NULL), m_lpstrHyperLink(NULL),
+                       m_hCursor(NULL), m_hFont(NULL), m_hFontNormal(NULL),
+                       m_clrLink(RGB(0, 0, 255)), m_clrVisited(RGB(128, 0, 128)),
+                       m_dwExtendedStyle(dwExtendedStyle),
+                       m_bPaintLabel(true), m_bVisited(false),
+                       m_bHover(false), m_bInternalLinkFont(false)
+       {
+               ::SetRectEmpty(&m_rcLink);
+       }
+
+       ~CHyperLinkImpl()
+       {
+               delete [] m_lpstrLabel;
+               delete [] m_lpstrHyperLink;
+               if(m_bInternalLinkFont && m_hFont != NULL)
+                       ::DeleteObject(m_hFont);
+#if (WINVER < 0x0500) && !defined(_WIN32_WCE)
+               // It was created, not loaded, so we have to destroy it
+               if(m_hCursor != NULL)
+                       ::DestroyCursor(m_hCursor);
+#endif // (WINVER < 0x0500) && !defined(_WIN32_WCE)
+       }
+
+// Attributes
+       DWORD GetHyperLinkExtendedStyle() const
+       {
+               return m_dwExtendedStyle;
+       }
+
+       DWORD SetHyperLinkExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
+       {
+               DWORD dwPrevStyle = m_dwExtendedStyle;
+               if(dwMask == 0)
+                       m_dwExtendedStyle = dwExtendedStyle;
+               else
+                       m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
+               return dwPrevStyle;
+       }
+
+       bool GetLabel(LPTSTR lpstrBuffer, int nLength) const
+       {
+               if(m_lpstrLabel == NULL)
+                       return false;
+               ATLASSERT(lpstrBuffer != NULL);
+               if(nLength <= lstrlen(m_lpstrLabel))
+                       return false;
+
+               SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrLabel);
+
+               return true;
+       }
+
+       bool SetLabel(LPCTSTR lpstrLabel)
+       {
+               delete [] m_lpstrLabel;
+               m_lpstrLabel = NULL;
+               int cchLen = lstrlen(lpstrLabel) + 1;
+               ATLTRY(m_lpstrLabel = new TCHAR[cchLen]);
+               if(m_lpstrLabel == NULL)
+                       return false;
+
+               SecureHelper::strcpy_x(m_lpstrLabel, cchLen, lpstrLabel);
+               T* pT = static_cast<T*>(this);
+               pT->CalcLabelRect();
+
+               if(m_hWnd != NULL)
+                       SetWindowText(lpstrLabel);   // Set this for accessibility
+
+               return true;
+       }
+
+       bool GetHyperLink(LPTSTR lpstrBuffer, int nLength) const
+       {
+               if(m_lpstrHyperLink == NULL)
+                       return false;
+               ATLASSERT(lpstrBuffer != NULL);
+               if(nLength <= lstrlen(m_lpstrHyperLink))
+                       return false;
+
+               SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrHyperLink);
+
+               return true;
+       }
+
+       bool SetHyperLink(LPCTSTR lpstrLink)
+       {
+               delete [] m_lpstrHyperLink;
+               m_lpstrHyperLink = NULL;
+               int cchLen = lstrlen(lpstrLink) + 1;
+               ATLTRY(m_lpstrHyperLink = new TCHAR[cchLen]);
+               if(m_lpstrHyperLink == NULL)
+                       return false;
+
+               SecureHelper::strcpy_x(m_lpstrHyperLink, cchLen, lpstrLink);
+               if(m_lpstrLabel == NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->CalcLabelRect();
+               }
+#ifndef _WIN32_WCE
+               if(m_tip.IsWindow())
+               {
+                       m_tip.Activate(TRUE);
+                       m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
+               }
+#endif // !_WIN32_WCE
+               return true;
+       }
+
+       HFONT GetLinkFont() const
+       {
+               return m_hFont;
+       }
+
+       void SetLinkFont(HFONT hFont)
+       {
+               if(m_bInternalLinkFont && m_hFont != NULL)
+               {
+                       ::DeleteObject(m_hFont);
+                       m_bInternalLinkFont = false;
+               }
+               m_hFont = hFont;
+       }
+
+       int GetIdealHeight() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
+                       return -1;
+               if(!m_bPaintLabel)
+                       return -1;
+
+               CClientDC dc(m_hWnd);
+               RECT rect = { 0 };
+               GetClientRect(&rect);
+               HFONT hFontOld = dc.SelectFont(m_hFontNormal);
+               RECT rcText = rect;
+               dc.DrawText(_T("NS"), -1, &rcText, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
+               dc.SelectFont(m_hFont);
+               RECT rcLink = rect;
+               dc.DrawText(_T("NS"), -1, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
+               dc.SelectFont(hFontOld);
+               return max(rcText.bottom - rcText.top, rcLink.bottom - rcLink.top);
+       }
+
+       bool GetIdealSize(SIZE& size) const
+       {
+               int cx = 0, cy = 0;
+               bool bRet = GetIdealSize(cx, cy);
+               if(bRet)
+               {
+                       size.cx = cx;
+                       size.cy = cy;
+               }
+               return bRet;
+       }
+
+       bool GetIdealSize(int& cx, int& cy) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
+                       return false;
+               if(!m_bPaintLabel)
+                       return false;
+
+               CClientDC dc(m_hWnd);
+               RECT rcClient = { 0 };
+               GetClientRect(&rcClient);
+               RECT rcAll = rcClient;
+
+               if(IsUsingTags())
+               {
+                       // find tags and label parts
+                       LPTSTR lpstrLeft = NULL;
+                       int cchLeft = 0;
+                       LPTSTR lpstrLink = NULL;
+                       int cchLink = 0;
+                       LPTSTR lpstrRight = NULL;
+                       int cchRight = 0;
+
+                       const T* pT = static_cast<const T*>(this);
+                       pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
+
+                       // get label part rects
+                       HFONT hFontOld = dc.SelectFont(m_hFontNormal);
+                       RECT rcLeft = rcClient;
+                       dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
+
+                       dc.SelectFont(m_hFont);
+                       RECT rcLink = { rcLeft.right, rcLeft.top, rcClient.right, rcClient.bottom };
+                       dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
+
+                       dc.SelectFont(m_hFontNormal);
+                       RECT rcRight = { rcLink.right, rcLink.top, rcClient.right, rcClient.bottom };
+                       dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
+
+                       dc.SelectFont(hFontOld);
+
+                       int cyMax = max(rcLeft.bottom, max(rcLink.bottom, rcRight.bottom));
+                       ::SetRect(&rcAll, rcLeft.left, rcLeft.top, rcRight.right, cyMax);
+               }
+               else
+               {
+                       HFONT hOldFont = NULL;
+                       if(m_hFont != NULL)
+                               hOldFont = dc.SelectFont(m_hFont);
+                       LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
+                       DWORD dwStyle = GetStyle();
+                       int nDrawStyle = DT_LEFT;
+                       if (dwStyle & SS_CENTER)
+                               nDrawStyle = DT_CENTER;
+                       else if (dwStyle & SS_RIGHT)
+                               nDrawStyle = DT_RIGHT;
+                       dc.DrawText(lpstrText, -1, &rcAll, nDrawStyle | DT_WORDBREAK | DT_CALCRECT);
+                       if(m_hFont != NULL)
+                               dc.SelectFont(hOldFont);
+                       if (dwStyle & SS_CENTER)
+                       {
+                               int dx = (rcClient.right - rcAll.right) / 2;
+                               ::OffsetRect(&rcAll, dx, 0);
+                       }
+                       else if (dwStyle & SS_RIGHT)
+                       {
+                               int dx = rcClient.right - rcAll.right;
+                               ::OffsetRect(&rcAll, dx, 0);
+                       }
+               }
+
+               cx = rcAll.right - rcAll.left;
+               cy = rcAll.bottom - rcAll.top;
+
+               return true;
+       }
+
+       // for command buttons only
+       bool GetToolTipText(LPTSTR lpstrBuffer, int nLength) const
+       {
+               ATLASSERT(IsCommandButton());
+               return GetHyperLink(lpstrBuffer, nLength);
+       }
+
+       bool SetToolTipText(LPCTSTR lpstrToolTipText)
+       {
+               ATLASSERT(IsCommandButton());
+               return SetHyperLink(lpstrToolTipText);
+       }
+
+// Operations
+       BOOL SubclassWindow(HWND hWnd)
+       {
+               ATLASSERT(m_hWnd == NULL);
+               ATLASSERT(::IsWindow(hWnd));
+#if (_MSC_VER >= 1300)
+               BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd);
+#else // !(_MSC_VER >= 1300)
+               typedef ATL::CWindowImpl< T, TBase, TWinTraits>   _baseClass;
+               BOOL bRet = _baseClass::SubclassWindow(hWnd);
+#endif // !(_MSC_VER >= 1300)
+               if(bRet)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->Init();
+               }
+               return bRet;
+       }
+
+       bool Navigate()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               bool bRet = true;
+               if(IsNotifyButton())
+               {
+                       NMHDR nmhdr = { m_hWnd, GetDlgCtrlID(), NM_CLICK };
+                       ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr);
+               }
+               else if(IsCommandButton())
+               {
+                       ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
+               }
+               else
+               {
+                       ATLASSERT(m_lpstrHyperLink != NULL);
+#ifndef _WIN32_WCE
+                       DWORD_PTR dwRet = (DWORD_PTR)::ShellExecute(0, _T("open"), m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL);
+                       bRet = (dwRet > 32);
+#else // CE specific
+                       SHELLEXECUTEINFO shExeInfo = { sizeof(SHELLEXECUTEINFO), 0, 0, L"open", m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL, 0, 0, 0, 0, 0, 0, 0 };
+                       ::ShellExecuteEx(&shExeInfo);
+                       DWORD_PTR dwRet = (DWORD_PTR)shExeInfo.hInstApp;
+                       bRet = (dwRet == 0) || (dwRet > 32);
+#endif // _WIN32_WCE
+                       ATLASSERT(bRet);
+                       if(bRet)
+                       {
+                               m_bVisited = true;
+                               Invalidate();
+                       }
+               }
+               return bRet;
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CHyperLinkImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
+#endif // !_WIN32_WCE
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+#endif // !_WIN32_WCE
+               MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
+               MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
+               MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
+#endif // !_WIN32_WCE
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+               MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
+               MESSAGE_HANDLER(WM_CHAR, OnChar)
+               MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
+               MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
+               MESSAGE_HANDLER(WM_ENABLE, OnEnable)
+               MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
+               MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
+               MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Init();
+               return 0;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_tip.IsWindow())
+               {
+                       m_tip.DestroyWindow();
+                       m_tip.m_hWnd = NULL;
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               MSG msg = { m_hWnd, uMsg, wParam, lParam };
+               if(m_tip.IsWindow() && IsUsingToolTip())
+                       m_tip.RelayEvent(&msg);
+               bHandled = FALSE;
+               return 1;
+       }
+#endif // !_WIN32_WCE
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;   // no background painting needed (we do it all during WM_PAINT)
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(!m_bPaintLabel)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               T* pT = static_cast<T*>(this);
+               if(wParam != NULL)
+               {
+                       pT->DoEraseBackground((HDC)wParam);
+                       pT->DoPaint((HDC)wParam);
+               }
+               else
+               {
+                       CPaintDC dc(m_hWnd);
+                       pT->DoEraseBackground(dc.m_hDC);
+                       pT->DoPaint(dc.m_hDC);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_bPaintLabel)
+                       Invalidate();
+               else
+                       bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+               if((m_lpstrHyperLink != NULL  || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
+               {
+                       ::SetCursor(m_hCursor);
+                       if(IsUnderlineHover())
+                       {
+                               if(!m_bHover)
+                               {
+                                       m_bHover = true;
+                                       InvalidateRect(&m_rcLink);
+                                       UpdateWindow();
+#ifndef _WIN32_WCE
+                                       StartTrackMouseLeave();
+#endif // !_WIN32_WCE
+                               }
+                       }
+               }
+               else
+               {
+                       if(IsUnderlineHover())
+                       {
+                               if(m_bHover)
+                               {
+                                       m_bHover = false;
+                                       InvalidateRect(&m_rcLink);
+                                       UpdateWindow();
+                               }
+                       }
+                       bHandled = FALSE;
+               }
+               return 0;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(IsUnderlineHover() && m_bHover)
+               {
+                       m_bHover = false;
+                       InvalidateRect(&m_rcLink);
+                       UpdateWindow();
+               }
+               return 0;
+       }
+#endif // !_WIN32_WCE
+
+       LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+               if(::PtInRect(&m_rcLink, pt))
+               {
+                       SetFocus();
+                       SetCapture();
+               }
+               return 0;
+       }
+
+       LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               if(GetCapture() == m_hWnd)
+               {
+                       ReleaseCapture();
+                       POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+                       if(::PtInRect(&m_rcLink, pt))
+                       {
+                               T* pT = static_cast<T*>(this);
+                               pT->Navigate();
+                       }
+               }
+               return 0;
+       }
+
+       LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(wParam == VK_RETURN || wParam == VK_SPACE)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->Navigate();
+               }
+               return 0;
+       }
+
+       LRESULT OnGetDlgCode(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return DLGC_WANTCHARS;
+       }
+
+       LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               POINT pt = { 0, 0 };
+               GetCursorPos(&pt);
+               ScreenToClient(&pt);
+               if((m_lpstrHyperLink != NULL  || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
+               {
+                       return TRUE;
+               }
+               bHandled = FALSE;
+               return FALSE;
+       }
+
+       LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               Invalidate();
+               UpdateWindow();
+               return 0;
+       }
+
+       LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return (LRESULT)m_hFontNormal;
+       }
+
+       LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               m_hFontNormal = (HFONT)wParam;
+               if((BOOL)lParam)
+               {
+                       Invalidate();
+                       UpdateWindow();
+               }
+               return 0;
+       }
+
+       LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // If the control is subclassed or superclassed, this message can cause
+               // repainting without WM_PAINT. We don't use this state, so just do nothing.
+               return 0;
+       }
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->CalcLabelRect();
+               pT->Invalidate();
+               return 0;
+       }
+
+// Implementation
+       void Init()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               // Check if we should paint a label
+               const int cchBuff = 8;
+               TCHAR szBuffer[cchBuff] = { 0 };
+               if(::GetClassName(m_hWnd, szBuffer, cchBuff))
+               {
+                       if(lstrcmpi(szBuffer, _T("static")) == 0)
+                       {
+                               ModifyStyle(0, SS_NOTIFY);   // we need this
+                               DWORD dwStyle = GetStyle() & 0x000000FF;
+#ifndef _WIN32_WCE
+                               if(dwStyle == SS_ICON || dwStyle == SS_BLACKRECT || dwStyle == SS_GRAYRECT || 
+                                               dwStyle == SS_WHITERECT || dwStyle == SS_BLACKFRAME || dwStyle == SS_GRAYFRAME || 
+                                               dwStyle == SS_WHITEFRAME || dwStyle == SS_OWNERDRAW || 
+                                               dwStyle == SS_BITMAP || dwStyle == SS_ENHMETAFILE)
+#else // CE specific
+                               if(dwStyle == SS_ICON || dwStyle == SS_BITMAP)
+#endif // _WIN32_WCE
+                                       m_bPaintLabel = false;
+                       }
+               }
+
+               // create or load a cursor
+#if (WINVER >= 0x0500) || defined(_WIN32_WCE)
+               m_hCursor = ::LoadCursor(NULL, IDC_HAND);
+#else
+               m_hCursor = ::CreateCursor(ModuleHelper::GetModuleInstance(), _AtlHyperLink_CursorData.xHotSpot, _AtlHyperLink_CursorData.yHotSpot, _AtlHyperLink_CursorData.cxWidth, _AtlHyperLink_CursorData.cyHeight, _AtlHyperLink_CursorData.arrANDPlane, _AtlHyperLink_CursorData.arrXORPlane);
+#endif
+               ATLASSERT(m_hCursor != NULL);
+
+               // set font
+               if(m_bPaintLabel)
+               {
+                       ATL::CWindow wnd = GetParent();
+                       m_hFontNormal = wnd.GetFont();
+                       if(m_hFontNormal == NULL)
+                               m_hFontNormal = (HFONT)::GetStockObject(SYSTEM_FONT);
+                       if(m_hFontNormal != NULL && m_hFont == NULL)
+                       {
+                               LOGFONT lf = { 0 };
+                               CFontHandle font = m_hFontNormal;
+                               font.GetLogFont(&lf);
+                               if(IsUsingTagsBold())
+                                       lf.lfWeight = FW_BOLD;
+                               else if(!IsNotUnderlined())
+                                       lf.lfUnderline = TRUE;
+                               m_hFont = ::CreateFontIndirect(&lf);
+                               m_bInternalLinkFont = true;
+                               ATLASSERT(m_hFont != NULL);
+                       }
+               }
+
+#ifndef _WIN32_WCE
+               // create a tool tip
+               m_tip.Create(m_hWnd);
+               ATLASSERT(m_tip.IsWindow());
+#endif // !_WIN32_WCE
+
+               // set label (defaults to window text)
+               if(m_lpstrLabel == NULL)
+               {
+                       int nLen = GetWindowTextLength();
+                       if(nLen > 0)
+                       {
+                               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+                               LPTSTR lpstrText = buff.Allocate(nLen + 1);
+                               ATLASSERT(lpstrText != NULL);
+                               if((lpstrText != NULL) && (GetWindowText(lpstrText, nLen + 1) > 0))
+                                       SetLabel(lpstrText);
+                       }
+               }
+
+               T* pT = static_cast<T*>(this);
+               pT->CalcLabelRect();
+
+               // set hyperlink (defaults to label), or just activate tool tip if already set
+               if(m_lpstrHyperLink == NULL && !IsCommandButton())
+               {
+                       if(m_lpstrLabel != NULL)
+                               SetHyperLink(m_lpstrLabel);
+               }
+#ifndef _WIN32_WCE
+               else
+               {
+                       m_tip.Activate(TRUE);
+                       m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
+               }
+#endif // !_WIN32_WCE
+
+               // set link colors
+               if(m_bPaintLabel)
+               {
+                       ATL::CRegKey rk;
+                       LONG lRet = rk.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Internet Explorer\\Settings"));
+                       if(lRet == 0)
+                       {
+                               const int cchValue = 12;
+                               TCHAR szValue[cchValue] = { 0 };
+#if (_ATL_VER >= 0x0700)
+                               ULONG ulCount = cchValue;
+                               lRet = rk.QueryStringValue(_T("Anchor Color"), szValue, &ulCount);
+#else
+                               DWORD dwCount = cchValue * sizeof(TCHAR);
+                               lRet = rk.QueryValue(szValue, _T("Anchor Color"), &dwCount);
+#endif
+                               if(lRet == 0)
+                               {
+                                       COLORREF clr = pT->_ParseColorString(szValue);
+                                       ATLASSERT(clr != CLR_INVALID);
+                                       if(clr != CLR_INVALID)
+                                               m_clrLink = clr;
+                               }
+
+#if (_ATL_VER >= 0x0700)
+                               ulCount = cchValue;
+                               lRet = rk.QueryStringValue(_T("Anchor Color Visited"), szValue, &ulCount);
+#else
+                               dwCount = cchValue * sizeof(TCHAR);
+                               lRet = rk.QueryValue(szValue, _T("Anchor Color Visited"), &dwCount);
+#endif
+                               if(lRet == 0)
+                               {
+                                       COLORREF clr = pT->_ParseColorString(szValue);
+                                       ATLASSERT(clr != CLR_INVALID);
+                                       if(clr != CLR_INVALID)
+                                               m_clrVisited = clr;
+                               }
+                       }
+               }
+       }
+
+       static COLORREF _ParseColorString(LPTSTR lpstr)
+       {
+               int c[3] = { -1, -1, -1 };
+               LPTSTR p = NULL;
+               for(int i = 0; i < 2; i++)
+               {
+                       for(p = lpstr; *p != _T('\0'); p = ::CharNext(p))
+                       {
+                               if(*p == _T(','))
+                               {
+                                       *p = _T('\0');
+                                       c[i] = T::_xttoi(lpstr);
+                                       lpstr = &p[1];
+                                       break;
+                               }
+                       }
+                       if(c[i] == -1)
+                               return CLR_INVALID;
+               }
+               if(*lpstr == _T('\0'))
+                       return CLR_INVALID;
+               c[2] = T::_xttoi(lpstr);
+
+               return RGB(c[0], c[1], c[2]);
+       }
+
+       bool CalcLabelRect()
+       {
+               if(!::IsWindow(m_hWnd))
+                       return false;
+               if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
+                       return false;
+
+               CClientDC dc(m_hWnd);
+               RECT rcClient = { 0 };
+               GetClientRect(&rcClient);
+               m_rcLink = rcClient;
+               if(!m_bPaintLabel)
+                       return true;
+
+               if(IsUsingTags())
+               {
+                       // find tags and label parts
+                       LPTSTR lpstrLeft = NULL;
+                       int cchLeft = 0;
+                       LPTSTR lpstrLink = NULL;
+                       int cchLink = 0;
+                       LPTSTR lpstrRight = NULL;
+                       int cchRight = 0;
+
+                       T* pT = static_cast<T*>(this);
+                       pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
+                       ATLASSERT(lpstrLink != NULL);
+                       ATLASSERT(cchLink > 0);
+
+                       // get label part rects
+                       HFONT hFontOld = dc.SelectFont(m_hFontNormal);
+
+                       RECT rcLeft = rcClient;
+                       if(lpstrLeft != NULL)
+                               dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
+
+                       dc.SelectFont(m_hFont);
+                       RECT rcLink = rcClient;
+                       if(lpstrLeft != NULL)
+                               rcLink.left = rcLeft.right;
+                       dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
+
+                       dc.SelectFont(hFontOld);
+
+                       m_rcLink = rcLink;
+               }
+               else
+               {
+                       HFONT hOldFont = NULL;
+                       if(m_hFont != NULL)
+                               hOldFont = dc.SelectFont(m_hFont);
+                       LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
+                       DWORD dwStyle = GetStyle();
+                       int nDrawStyle = DT_LEFT;
+                       if (dwStyle & SS_CENTER)
+                               nDrawStyle = DT_CENTER;
+                       else if (dwStyle & SS_RIGHT)
+                               nDrawStyle = DT_RIGHT;
+                       dc.DrawText(lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK | DT_CALCRECT);
+                       if(m_hFont != NULL)
+                               dc.SelectFont(hOldFont);
+                       if (dwStyle & SS_CENTER)
+                       {
+                               int dx = (rcClient.right - m_rcLink.right) / 2;
+                               ::OffsetRect(&m_rcLink, dx, 0);
+                       }
+                       else if (dwStyle & SS_RIGHT)
+                       {
+                               int dx = rcClient.right - m_rcLink.right;
+                               ::OffsetRect(&m_rcLink, dx, 0);
+                       }
+               }
+
+               return true;
+       }
+
+       void CalcLabelParts(LPTSTR& lpstrLeft, int& cchLeft, LPTSTR& lpstrLink, int& cchLink, LPTSTR& lpstrRight, int& cchRight) const
+       {
+               lpstrLeft = NULL;
+               cchLeft = 0;
+               lpstrLink = NULL;
+               cchLink = 0;
+               lpstrRight = NULL;
+               cchRight = 0;
+
+               LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
+               int cchText = lstrlen(lpstrText);
+               bool bOutsideLink = true;
+               for(int i = 0; i < cchText; i++)
+               {
+                       if(lpstrText[i] != _T('<'))
+                               continue;
+
+                       if(bOutsideLink)
+                       {
+                               if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 3, _T("<A>"), 3) == CSTR_EQUAL)
+                               {
+                                       if(i > 0)
+                                       {
+                                               lpstrLeft = lpstrText;
+                                               cchLeft = i;
+                                       }
+                                       lpstrLink = &lpstrText[i + 3];
+                                       bOutsideLink = false;
+                               }
+                       }
+                       else
+                       {
+                               if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 4, _T("</A>"), 4) == CSTR_EQUAL)
+                               {
+                                       cchLink = i - 3 - cchLeft;
+                                       if(lpstrText[i + 4] != 0)
+                                       {
+                                               lpstrRight = &lpstrText[i + 4];
+                                               cchRight = cchText - (i + 4);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+       }
+
+       void DoEraseBackground(CDCHandle dc)
+       {
+               HBRUSH hBrush = (HBRUSH)::SendMessage(GetParent(), WM_CTLCOLORSTATIC, (WPARAM)dc.m_hDC, (LPARAM)m_hWnd);
+               if(hBrush != NULL)
+               {
+                       RECT rect = { 0 };
+                       GetClientRect(&rect);
+                       dc.FillRect(&rect, hBrush);
+               }
+       }
+
+       void DoPaint(CDCHandle dc)
+       {
+               if(IsUsingTags())
+               {
+                       // find tags and label parts
+                       LPTSTR lpstrLeft = NULL;
+                       int cchLeft = 0;
+                       LPTSTR lpstrLink = NULL;
+                       int cchLink = 0;
+                       LPTSTR lpstrRight = NULL;
+                       int cchRight = 0;
+
+                       T* pT = static_cast<T*>(this);
+                       pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
+
+                       // get label part rects
+                       RECT rcClient = { 0 };
+                       GetClientRect(&rcClient);
+
+                       dc.SetBkMode(TRANSPARENT);
+                       HFONT hFontOld = dc.SelectFont(m_hFontNormal);
+
+                       if(lpstrLeft != NULL)
+                               dc.DrawText(lpstrLeft, cchLeft, &rcClient, DT_LEFT | DT_WORDBREAK);
+
+                       COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
+                       if(m_hFont != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
+                               dc.SelectFont(m_hFont);
+                       else
+                               dc.SelectFont(m_hFontNormal);
+
+                       dc.DrawText(lpstrLink, cchLink, &m_rcLink, DT_LEFT | DT_WORDBREAK);
+
+                       dc.SetTextColor(clrOld);
+                       dc.SelectFont(m_hFontNormal);
+                       if(lpstrRight != NULL)
+                       {
+                               RECT rcRight = { m_rcLink.right, m_rcLink.top, rcClient.right, rcClient.bottom };
+                               dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | DT_WORDBREAK);
+                       }
+
+                       if(GetFocus() == m_hWnd)
+                               dc.DrawFocusRect(&m_rcLink);
+
+                       dc.SelectFont(hFontOld);
+               }
+               else
+               {
+                       dc.SetBkMode(TRANSPARENT);
+                       COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
+
+                       HFONT hFontOld = NULL;
+                       if(m_hFont != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
+                               hFontOld = dc.SelectFont(m_hFont);
+                       else
+                               hFontOld = dc.SelectFont(m_hFontNormal);
+
+                       LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
+
+                       DWORD dwStyle = GetStyle();
+                       int nDrawStyle = DT_LEFT;
+                       if (dwStyle & SS_CENTER)
+                               nDrawStyle = DT_CENTER;
+                       else if (dwStyle & SS_RIGHT)
+                               nDrawStyle = DT_RIGHT;
+
+                       dc.DrawText(lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK);
+
+                       if(GetFocus() == m_hWnd)
+                               dc.DrawFocusRect(&m_rcLink);
+
+                       dc.SetTextColor(clrOld);
+                       dc.SelectFont(hFontOld);
+               }
+       }
+
+#ifndef _WIN32_WCE
+       BOOL StartTrackMouseLeave()
+       {
+               TRACKMOUSEEVENT tme = { 0 };
+               tme.cbSize = sizeof(tme);
+               tme.dwFlags = TME_LEAVE;
+               tme.hwndTrack = m_hWnd;
+               return _TrackMouseEvent(&tme);
+       }
+#endif // !_WIN32_WCE
+
+// Implementation helpers
+       bool IsUnderlined() const
+       {
+               return ((m_dwExtendedStyle & (HLINK_NOTUNDERLINED | HLINK_UNDERLINEHOVER)) == 0);
+       }
+
+       bool IsNotUnderlined() const
+       {
+               return ((m_dwExtendedStyle & HLINK_NOTUNDERLINED) != 0);
+       }
+
+       bool IsUnderlineHover() const
+       {
+               return ((m_dwExtendedStyle & HLINK_UNDERLINEHOVER) != 0);
+       }
+
+       bool IsCommandButton() const
+       {
+               return ((m_dwExtendedStyle & HLINK_COMMANDBUTTON) != 0);
+       }
+
+       bool IsNotifyButton() const
+       {
+               return ((m_dwExtendedStyle & HLINK_NOTIFYBUTTON) == HLINK_NOTIFYBUTTON);
+       }
+
+       bool IsUsingTags() const
+       {
+               return ((m_dwExtendedStyle & HLINK_USETAGS) != 0);
+       }
+
+       bool IsUsingTagsBold() const
+       {
+               return ((m_dwExtendedStyle & HLINK_USETAGSBOLD) == HLINK_USETAGSBOLD);
+       }
+
+       bool IsUsingToolTip() const
+       {
+               return ((m_dwExtendedStyle & HLINK_NOTOOLTIP) == 0);
+       }
+
+       static int _xttoi(const TCHAR* nptr)
+       {
+#ifndef _ATL_MIN_CRT
+               return _ttoi(nptr);
+#else // _ATL_MIN_CRT
+               while(*nptr == _T(' '))   // skip spaces
+                       ++nptr;
+
+               int c = (int)(_TUCHAR)*nptr++;
+               int sign = c;   // save sign indication
+               if (c == _T('-') || c == _T('+'))
+                       c = (int)(_TUCHAR)*nptr++;   // skip sign
+
+               int total = 0;
+               while((TCHAR)c >= _T('0') && (TCHAR)c <= _T('9'))
+               {
+                       total = 10 * total + ((TCHAR)c - _T('0'));   // accumulate digit
+                       c = (int)(_TUCHAR)*nptr++;        // get next char
+               }
+
+               // return result, negated if necessary
+               return ((TCHAR)sign != _T('-')) ? total : -total;
+#endif // _ATL_MIN_CRT
+       }
+};
+
+
+class CHyperLink : public CHyperLinkImpl<CHyperLink>
+{
+public:
+       DECLARE_WND_CLASS(_T("WTL_HyperLink"))
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CWaitCursor - displays a wait cursor
+
+class CWaitCursor
+{
+public:
+// Data
+       HCURSOR m_hWaitCursor;
+       HCURSOR m_hOldCursor;
+       bool m_bInUse;
+
+// Constructor/destructor
+       CWaitCursor(bool bSet = true, LPCTSTR lpstrCursor = IDC_WAIT, bool bSys = true) : m_hOldCursor(NULL), m_bInUse(false)
+       {
+               HINSTANCE hInstance = bSys ? NULL : ModuleHelper::GetResourceInstance();
+               m_hWaitCursor = ::LoadCursor(hInstance, lpstrCursor);
+               ATLASSERT(m_hWaitCursor != NULL);
+
+               if(bSet)
+                       Set();
+       }
+
+       ~CWaitCursor()
+       {
+               Restore();
+       }
+
+// Methods
+       bool Set()
+       {
+               if(m_bInUse)
+                       return false;
+               m_hOldCursor = ::SetCursor(m_hWaitCursor);
+               m_bInUse = true;
+               return true;
+       }
+
+       bool Restore()
+       {
+               if(!m_bInUse)
+                       return false;
+               ::SetCursor(m_hOldCursor);
+               m_bInUse = false;
+               return true;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CCustomWaitCursor - for custom and animated cursors
+
+class CCustomWaitCursor : public CWaitCursor
+{
+public:
+// Constructor/destructor
+       CCustomWaitCursor(ATL::_U_STRINGorID cursor, bool bSet = true, HINSTANCE hInstance = NULL) : 
+                       CWaitCursor(false, IDC_WAIT, true)
+       {
+               if(hInstance == NULL)
+                       hInstance = ModuleHelper::GetResourceInstance();
+               m_hWaitCursor = (HCURSOR)::LoadImage(hInstance, cursor.m_lpstr, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
+
+               if(bSet)
+                       Set();
+       }
+
+       ~CCustomWaitCursor()
+       {
+               Restore();
+#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
+               ::DestroyCursor(m_hWaitCursor);
+#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMultiPaneStatusBarCtrl - Status Bar with multiple panes
+
+template <class T, class TBase = CStatusBarCtrl>
+class ATL_NO_VTABLE CMultiPaneStatusBarCtrlImpl : public ATL::CWindowImpl< T, TBase >
+{
+public:
+       DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
+
+// Data
+       enum { m_cxPaneMargin = 3 };
+
+       int m_nPanes;
+       int* m_pPane;
+
+// Constructor/destructor
+       CMultiPaneStatusBarCtrlImpl() : m_nPanes(0), m_pPane(NULL)
+       { }
+
+       ~CMultiPaneStatusBarCtrlImpl()
+       {
+               delete [] m_pPane;
+       }
+
+// Methods
+       HWND Create(HWND hWndParent, LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
+       {
+#if (_MSC_VER >= 1300)
+               return ATL::CWindowImpl< T, TBase >::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID);
+#else // !(_MSC_VER >= 1300)
+               typedef ATL::CWindowImpl< T, TBase >   _baseClass;
+               return _baseClass::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID);
+#endif // !(_MSC_VER >= 1300)
+       }
+
+       HWND Create(HWND hWndParent, UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
+       {
+               const int cchMax = 128;   // max text length is 127 for status bars (+1 for null)
+               TCHAR szText[cchMax];
+               szText[0] = 0;
+               ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
+               return Create(hWndParent, szText, dwStyle, nID);
+       }
+
+       BOOL SetPanes(int* pPanes, int nPanes, bool bSetText = true)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPanes > 0);
+
+               m_nPanes = nPanes;
+               delete [] m_pPane;
+               m_pPane = NULL;
+
+               ATLTRY(m_pPane = new int[nPanes]);
+               ATLASSERT(m_pPane != NULL);
+               if(m_pPane == NULL)
+                       return FALSE;
+
+               CTempBuffer<int, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               int* pPanesPos = buff.Allocate(nPanes);
+               ATLASSERT(pPanesPos != NULL);
+               if(pPanesPos == NULL)
+                       return FALSE;
+
+               SecureHelper::memcpy_x(m_pPane, nPanes * sizeof(int), pPanes, nPanes * sizeof(int));
+
+               // get status bar DC and set font
+               CClientDC dc(m_hWnd);
+               HFONT hOldFont = dc.SelectFont(GetFont());
+
+               // get status bar borders
+               int arrBorders[3] = { 0 };
+               GetBorders(arrBorders);
+
+               const int cchBuff = 128;
+               TCHAR szBuff[cchBuff] = { 0 };
+               SIZE size = { 0, 0 };
+               int cxLeft = arrBorders[0];
+
+               // calculate right edge of each part
+               for(int i = 0; i < nPanes; i++)
+               {
+                       if(pPanes[i] == ID_DEFAULT_PANE)
+                       {
+                               // make very large, will be resized later
+                               pPanesPos[i] = INT_MAX / 2;
+                       }
+                       else
+                       {
+                               ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff);
+                               dc.GetTextExtent(szBuff, lstrlen(szBuff), &size);
+                               T* pT = static_cast<T*>(this);
+                               pT;
+                               pPanesPos[i] = cxLeft + size.cx + arrBorders[2] + 2 * pT->m_cxPaneMargin;
+                       }
+                       cxLeft = pPanesPos[i];
+               }
+
+               BOOL bRet = SetParts(nPanes, pPanesPos);
+
+               if(bRet && bSetText)
+               {
+                       for(int i = 0; i < nPanes; i++)
+                       {
+                               if(pPanes[i] != ID_DEFAULT_PANE)
+                               {
+                                       ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff);
+                                       SetPaneText(m_pPane[i], szBuff);
+                               }
+                       }
+               }
+
+               dc.SelectFont(hOldFont);
+               return bRet;
+       }
+
+       bool GetPaneTextLength(int nPaneID, int* pcchLength = NULL, int* pnType = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return false;
+
+               int nLength = GetTextLength(nIndex, pnType);
+               if(pcchLength != NULL)
+                       *pcchLength = nLength;
+
+               return true;
+       }
+
+       BOOL GetPaneText(int nPaneID, LPTSTR lpstrText, int* pcchLength = NULL, int* pnType = NULL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return FALSE;
+
+               int nLength = GetText(nIndex, lpstrText, pnType);
+               if(pcchLength != NULL)
+                       *pcchLength = nLength;
+
+               return TRUE;
+       }
+
+       BOOL SetPaneText(int nPaneID, LPCTSTR lpstrText, int nType = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return FALSE;
+
+               return SetText(nIndex, lpstrText, nType);
+       }
+
+       BOOL GetPaneRect(int nPaneID, LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return FALSE;
+
+               return GetRect(nIndex, lpRect);
+       }
+
+       BOOL SetPaneWidth(int nPaneID, int cxWidth)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPaneID != ID_DEFAULT_PANE);   // Can't resize this one
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return FALSE;
+
+               // get pane positions
+               CTempBuffer<int, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               int* pPanesPos = buff.Allocate(m_nPanes);
+               if(pPanesPos == NULL)
+                       return FALSE;
+               GetParts(m_nPanes, pPanesPos);
+               // calculate offset
+               int cxPaneWidth = pPanesPos[nIndex] - ((nIndex == 0) ? 0 : pPanesPos[nIndex - 1]);
+               int cxOff = cxWidth - cxPaneWidth;
+               // find variable width pane
+               int nDef = m_nPanes;
+               for(int i = 0; i < m_nPanes; i++)
+               {
+                       if(m_pPane[i] == ID_DEFAULT_PANE)
+                       {
+                               nDef = i;
+                               break;
+                       }
+               }
+               // resize
+               if(nIndex < nDef)   // before default pane
+               {
+                       for(int i = nIndex; i < nDef; i++)
+                               pPanesPos[i] += cxOff;
+                               
+               }
+               else                    // after default one
+               {
+                       for(int i = nDef; i < nIndex; i++)
+                               pPanesPos[i] -= cxOff;
+               }
+               // set pane postions
+               return SetParts(m_nPanes, pPanesPos);
+       }
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       BOOL GetPaneTipText(int nPaneID, LPTSTR lpstrText, int nSize) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return FALSE;
+
+               GetTipText(nIndex, lpstrText, nSize);
+               return TRUE;
+       }
+
+       BOOL SetPaneTipText(int nPaneID, LPCTSTR lpstrText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return FALSE;
+
+               SetTipText(nIndex, lpstrText);
+               return TRUE;
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+#if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500))
+       BOOL GetPaneIcon(int nPaneID, HICON& hIcon) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return FALSE;
+
+               hIcon = GetIcon(nIndex);
+               return TRUE;
+       }
+
+       BOOL SetPaneIcon(int nPaneID, HICON hIcon)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               int nIndex  = GetPaneIndexFromID(nPaneID);
+               if(nIndex == -1)
+                       return FALSE;
+
+               return SetIcon(nIndex, hIcon);
+       }
+#endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500))
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CMultiPaneStatusBarCtrlImpl< T >)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+       END_MSG_MAP()
+
+       LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               if(wParam != SIZE_MINIMIZED && m_nPanes > 0)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdatePanesLayout();
+               }
+               return lRet;
+       }
+
+// Implementation
+       BOOL UpdatePanesLayout()
+       {
+               // get pane positions
+               CTempBuffer<int, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               int* pPanesPos = buff.Allocate(m_nPanes);
+               ATLASSERT(pPanesPos != NULL);
+               if(pPanesPos == NULL)
+                       return FALSE;
+               int nRet = GetParts(m_nPanes, pPanesPos);
+               ATLASSERT(nRet == m_nPanes);
+               if(nRet != m_nPanes)
+                       return FALSE;
+               // calculate offset
+               RECT rcClient = { 0 };
+               GetClientRect(&rcClient);
+               int cxOff = rcClient.right - pPanesPos[m_nPanes - 1];
+#ifndef _WIN32_WCE
+               // Move panes left if size grip box is present
+               if((GetStyle() & SBARS_SIZEGRIP) != 0)
+                       cxOff -= ::GetSystemMetrics(SM_CXVSCROLL) + ::GetSystemMetrics(SM_CXEDGE);
+#endif // !_WIN32_WCE
+               // find variable width pane
+               int i;
+               for(i = 0; i < m_nPanes; i++)
+               {
+                       if(m_pPane[i] == ID_DEFAULT_PANE)
+                               break;
+               }
+               // resize all panes from the variable one to the right
+               if((i < m_nPanes) && (pPanesPos[i] + cxOff) > ((i == 0) ? 0 : pPanesPos[i - 1]))
+               {
+                       for(; i < m_nPanes; i++)
+                               pPanesPos[i] += cxOff;
+               }
+               // set pane postions
+               return SetParts(m_nPanes, pPanesPos);
+       }
+
+       int GetPaneIndexFromID(int nPaneID) const
+       {
+               for(int i = 0; i < m_nPanes; i++)
+               {
+                       if(m_pPane[i] == nPaneID)
+                               return i;
+               }
+
+               return -1;   // not found
+       }
+};
+
+class CMultiPaneStatusBarCtrl : public CMultiPaneStatusBarCtrlImpl<CMultiPaneStatusBarCtrl>
+{
+public:
+       DECLARE_WND_SUPERCLASS(_T("WTL_MultiPaneStatusBar"), GetWndClassName())
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPaneContainer - provides header with title and close button for panes
+
+// pane container extended styles
+#define PANECNT_NOCLOSEBUTTON  0x00000001
+#define PANECNT_VERTICAL       0x00000002
+#define PANECNT_FLATBORDER     0x00000004
+#define PANECNT_NOBORDER       0x00000008
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CPaneContainerImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CCustomDraw< T >
+{
+public:
+       DECLARE_WND_CLASS_EX(NULL, 0, -1)
+
+// Constants
+       enum
+       {
+               m_cxyBorder = 2,
+               m_cxyTextOffset = 4,
+               m_cxyBtnOffset = 1,
+
+               m_cchTitle = 80,
+
+               m_cxImageTB = 13,
+               m_cyImageTB = 11,
+               m_cxyBtnAddTB = 7,
+
+               m_cxToolBar = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder + m_cxyBtnOffset,
+
+               m_xBtnImageLeft = 6,
+               m_yBtnImageTop = 5,
+               m_xBtnImageRight = 12,
+               m_yBtnImageBottom = 11,
+
+               m_nCloseBtnID = ID_PANE_CLOSE
+       };
+
+// Data members
+       CToolBarCtrl m_tb;
+       ATL::CWindow m_wndClient;
+       int m_cxyHeader;
+       TCHAR m_szTitle[m_cchTitle];
+       DWORD m_dwExtendedStyle;   // Pane container specific extended styles
+
+
+// Constructor
+       CPaneContainerImpl() : m_cxyHeader(0), m_dwExtendedStyle(0)
+       {
+               m_szTitle[0] = 0;
+       }
+
+// Attributes
+       DWORD GetPaneContainerExtendedStyle() const
+       {
+               return m_dwExtendedStyle;
+       }
+
+       DWORD SetPaneContainerExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
+       {
+               DWORD dwPrevStyle = m_dwExtendedStyle;
+               if(dwMask == 0)
+                       m_dwExtendedStyle = dwExtendedStyle;
+               else
+                       m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
+               if(m_hWnd != NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       bool bUpdate = false;
+
+                       if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) != 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0))   // add close button
+                       {
+                               pT->CreateCloseButton();
+                               bUpdate = true;
+                       }
+                       else if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) == 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) != 0))   // remove close button
+                       {
+                               pT->DestroyCloseButton();
+                               bUpdate = true;
+                       }
+
+                       if((dwPrevStyle & PANECNT_VERTICAL) != (m_dwExtendedStyle & PANECNT_VERTICAL))   // change orientation
+                       {
+                               pT->CalcSize();
+                               bUpdate = true;
+                       }
+
+                       if((dwPrevStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER)) != 
+                          (m_dwExtendedStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER)))   // change border
+                       {
+                               bUpdate = true;
+                       }
+
+                       if(bUpdate)
+                               pT->UpdateLayout();
+               }
+               return dwPrevStyle;
+       }
+
+       HWND GetClient() const
+       {
+               return m_wndClient;
+       }
+
+       HWND SetClient(HWND hWndClient)
+       {
+               HWND hWndOldClient = m_wndClient;
+               m_wndClient = hWndClient;
+               if(m_hWnd != NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateLayout();
+               }
+               return hWndOldClient;
+       }
+
+       BOOL GetTitle(LPTSTR lpstrTitle, int cchLength) const
+       {
+               ATLASSERT(lpstrTitle != NULL);
+
+               errno_t nRet = SecureHelper::strncpy_x(lpstrTitle, cchLength, m_szTitle, _TRUNCATE);
+
+               return (nRet == 0 || nRet == STRUNCATE);
+       }
+
+       BOOL SetTitle(LPCTSTR lpstrTitle)
+       {
+               ATLASSERT(lpstrTitle != NULL);
+
+               errno_t nRet = SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE);
+               bool bRet = (nRet == 0 || nRet == STRUNCATE);
+               if(bRet && m_hWnd != NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateLayout();
+               }
+
+               return bRet;
+       }
+
+       int GetTitleLength() const
+       {
+               return lstrlen(m_szTitle);
+       }
+
+// Methods
+       HWND Create(HWND hWndParent, LPCTSTR lpstrTitle = NULL, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+                       DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
+       {
+               if(lpstrTitle != NULL)
+                       SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE);
+#if (_MSC_VER >= 1300)
+               return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
+#else // !(_MSC_VER >= 1300)
+               typedef ATL::CWindowImpl< T, TBase, TWinTraits >   _baseClass;
+               return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
+#endif // !(_MSC_VER >= 1300)
+       }
+
+       HWND Create(HWND hWndParent, UINT uTitleID, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+                       DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
+       {
+               if(uTitleID != 0U)
+                       ::LoadString(ModuleHelper::GetResourceInstance(), uTitleID, m_szTitle, m_cchTitle);
+#if (_MSC_VER >= 1300)
+               return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
+#else // !(_MSC_VER >= 1300)
+               typedef ATL::CWindowImpl< T, TBase, TWinTraits >   _baseClass;
+               return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
+#endif // !(_MSC_VER >= 1300)
+       }
+
+       BOOL EnableCloseButton(BOOL bEnable)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+               return (m_tb.m_hWnd != NULL) ? m_tb.EnableButton(pT->m_nCloseBtnID, bEnable) : FALSE;
+       }
+
+       void UpdateLayout()
+       {
+               RECT rcClient = { 0 };
+               GetClientRect(&rcClient);
+               T* pT = static_cast<T*>(this);
+               pT->UpdateLayout(rcClient.right, rcClient.bottom);
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CPaneContainerImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+#endif // !_WIN32_WCE
+               MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
+               MESSAGE_HANDLER(WM_COMMAND, OnCommand)
+               FORWARD_NOTIFICATIONS()
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->CalcSize();
+
+               if((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0)
+                       pT->CreateCloseButton();
+
+               return 0;
+       }
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+               return 0;
+       }
+
+       LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(m_wndClient.m_hWnd != NULL)
+                       m_wndClient.SetFocus();
+               return 0;
+       }
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;   // no background needed
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               if(wParam != NULL)
+               {
+                       pT->DrawPaneTitle((HDC)wParam);
+
+                       if(m_wndClient.m_hWnd == NULL)   // no client window
+                               pT->DrawPane((HDC)wParam);
+               }
+               else
+               {
+                       CPaintDC dc(m_hWnd);
+                       pT->DrawPaneTitle(dc.m_hDC);
+
+                       if(m_wndClient.m_hWnd == NULL)   // no client window
+                               pT->DrawPane(dc.m_hDC);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(m_tb.m_hWnd == NULL)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               T* pT = static_cast<T*>(this);
+               pT;
+               LPNMHDR lpnmh = (LPNMHDR)lParam;
+               LRESULT lRet = 0;
+
+               // pass toolbar custom draw notifications to the base class
+               if(lpnmh->code == NM_CUSTOMDRAW && lpnmh->hwndFrom == m_tb.m_hWnd)
+                       lRet = CCustomDraw< T >::OnCustomDraw(0, lpnmh, bHandled);
+#ifndef _WIN32_WCE
+               // tooltip notifications come with the tooltip window handle and button ID,
+               // pass them to the parent if we don't handle them
+               else if(lpnmh->code == TTN_GETDISPINFO && lpnmh->idFrom == pT->m_nCloseBtnID)
+                       bHandled = pT->GetToolTipText(lpnmh);
+#endif // !_WIN32_WCE
+               // only let notifications not from the toolbar go to the parent
+               else if(lpnmh->hwndFrom != m_tb.m_hWnd && lpnmh->idFrom != pT->m_nCloseBtnID)
+                       bHandled = FALSE;
+
+               return lRet;
+       }
+
+       LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               // if command comes from the close button, substitute HWND of the pane container instead
+               if(m_tb.m_hWnd != NULL && (HWND)lParam == m_tb.m_hWnd)
+                       return ::SendMessage(GetParent(), WM_COMMAND, wParam, (LPARAM)m_hWnd);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+// Custom draw overrides
+       DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
+       {
+               return CDRF_NOTIFYITEMDRAW;   // we need per-item notifications
+       }
+
+       DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
+       {
+               CDCHandle dc = lpNMCustomDraw->hdc;
+#if (_WIN32_IE >= 0x0400)
+               RECT& rc = lpNMCustomDraw->rc;
+#else // !(_WIN32_IE >= 0x0400)
+               RECT rc;
+               m_tb.GetItemRect(0, &rc);
+#endif // !(_WIN32_IE >= 0x0400)
+
+               dc.FillRect(&rc, COLOR_3DFACE);
+
+               return CDRF_NOTIFYPOSTPAINT;
+       }
+
+       DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
+       {
+               CDCHandle dc = lpNMCustomDraw->hdc;
+#if (_WIN32_IE >= 0x0400)
+               RECT& rc = lpNMCustomDraw->rc;
+#else // !(_WIN32_IE >= 0x0400)
+               RECT rc = { 0 };
+               m_tb.GetItemRect(0, &rc);
+#endif // !(_WIN32_IE >= 0x0400)
+
+               RECT rcImage = { m_xBtnImageLeft, m_yBtnImageTop, m_xBtnImageRight + 1, m_yBtnImageBottom + 1 };
+               ::OffsetRect(&rcImage, rc.left, rc.top);
+               T* pT = static_cast<T*>(this);
+
+               if((lpNMCustomDraw->uItemState & CDIS_DISABLED) != 0)
+               {
+                       RECT rcShadow = rcImage;
+                       ::OffsetRect(&rcShadow, 1, 1);
+                       CPen pen1;
+                       pen1.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT));
+                       pT->DrawButtonImage(dc, rcShadow, pen1);
+                       CPen pen2;
+                       pen2.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW));
+                       pT->DrawButtonImage(dc, rcImage, pen2);
+               }
+               else
+               {
+                       if((lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0)
+                               ::OffsetRect(&rcImage, 1, 1);
+                       CPen pen;
+                       pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT));
+                       pT->DrawButtonImage(dc, rcImage, pen);
+               }
+
+               return CDRF_DODEFAULT;   // continue with the default item painting
+       }
+
+// Implementation - overrideable methods
+       void UpdateLayout(int cxWidth, int cyHeight)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               RECT rect = { 0 };
+
+               if(IsVertical())
+               {
+                       ::SetRect(&rect, 0, 0, m_cxyHeader, cyHeight);
+                       if(m_tb.m_hWnd != NULL)
+                               m_tb.SetWindowPos(NULL, m_cxyBorder, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+
+                       if(m_wndClient.m_hWnd != NULL)
+                               m_wndClient.SetWindowPos(NULL, m_cxyHeader, 0, cxWidth - m_cxyHeader, cyHeight, SWP_NOZORDER);
+                       else
+                               rect.right = cxWidth;
+               }
+               else
+               {
+                       ::SetRect(&rect, 0, 0, cxWidth, m_cxyHeader);
+                       if(m_tb.m_hWnd != NULL)
+                               m_tb.SetWindowPos(NULL, rect.right - m_cxToolBar, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+
+                       if(m_wndClient.m_hWnd != NULL)
+                               m_wndClient.SetWindowPos(NULL, 0, m_cxyHeader, cxWidth, cyHeight - m_cxyHeader, SWP_NOZORDER);
+                       else
+                               rect.bottom = cyHeight;
+               }
+
+               InvalidateRect(&rect);
+       }
+
+       void CreateCloseButton()
+       {
+               ATLASSERT(m_tb.m_hWnd == NULL);
+               // create toolbar for the "x" button
+               m_tb.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NOMOVEY | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT, 0);
+               ATLASSERT(m_tb.IsWindow());
+
+               if(m_tb.m_hWnd != NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT;   // avoid level 4 warning
+
+                       m_tb.SetButtonStructSize();
+
+                       TBBUTTON tbbtn = { 0 };
+                       tbbtn.idCommand = pT->m_nCloseBtnID;
+                       tbbtn.fsState = TBSTATE_ENABLED;
+                       tbbtn.fsStyle = TBSTYLE_BUTTON;
+                       m_tb.AddButtons(1, &tbbtn);
+
+                       m_tb.SetBitmapSize(m_cxImageTB, m_cyImageTB);
+                       m_tb.SetButtonSize(m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB);
+
+                       if(IsVertical())
+                               m_tb.SetWindowPos(NULL, m_cxyBorder + m_cxyBtnOffset, m_cxyBorder + m_cxyBtnOffset, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB, SWP_NOZORDER | SWP_NOACTIVATE);
+                       else
+                               m_tb.SetWindowPos(NULL, 0, 0, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+               }
+       }
+
+       void DestroyCloseButton()
+       {
+               if(m_tb.m_hWnd != NULL)
+                       m_tb.DestroyWindow();
+       }
+
+       void CalcSize()
+       {
+               T* pT = static_cast<T*>(this);
+               CFontHandle font = pT->GetTitleFont();
+               LOGFONT lf = { 0 };
+               font.GetLogFont(lf);
+               if(IsVertical())
+               {
+                       m_cxyHeader = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder;
+               }
+               else
+               {
+                       int cyFont = abs(lf.lfHeight) + m_cxyBorder + 2 * m_cxyTextOffset;
+                       int cyBtn = m_cyImageTB + m_cxyBtnAddTB + m_cxyBorder + 2 * m_cxyBtnOffset;
+                       m_cxyHeader = max(cyFont, cyBtn);
+               }
+       }
+
+       HFONT GetTitleFont() const
+       {
+               return AtlGetDefaultGuiFont();
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetToolTipText(LPNMHDR /*lpnmh*/)
+       {
+               return FALSE;
+       }
+#endif // !_WIN32_WCE
+
+       void DrawPaneTitle(CDCHandle dc)
+       {
+               RECT rect = { 0 };
+               GetClientRect(&rect);
+
+               UINT uBorder = BF_LEFT | BF_TOP | BF_ADJUST;
+               if(IsVertical())
+               {
+                       rect.right = rect.left + m_cxyHeader;
+                       uBorder |= BF_BOTTOM;
+               }
+               else
+               {
+                       rect.bottom = rect.top + m_cxyHeader;
+                       uBorder |= BF_RIGHT;
+               }
+
+               if((m_dwExtendedStyle & PANECNT_NOBORDER) == 0)
+               {
+                       if((m_dwExtendedStyle & PANECNT_FLATBORDER) != 0)
+                               uBorder |= BF_FLAT;
+                       dc.DrawEdge(&rect, EDGE_ETCHED, uBorder);
+               }
+               dc.FillRect(&rect, COLOR_3DFACE);
+
+               if(!IsVertical())   // draw title only for horizontal pane container
+               {
+                       dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
+                       dc.SetBkMode(TRANSPARENT);
+                       T* pT = static_cast<T*>(this);
+                       HFONT hFontOld = dc.SelectFont(pT->GetTitleFont());
+                       rect.left += m_cxyTextOffset;
+                       rect.right -= m_cxyTextOffset;
+                       if(m_tb.m_hWnd != NULL)
+                               rect.right -= m_cxToolBar;;
+#ifndef _WIN32_WCE
+                       dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
+#else // CE specific
+                       dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
+#endif // _WIN32_WCE
+                       dc.SelectFont(hFontOld);
+               }
+       }
+
+       // called only if pane is empty
+       void DrawPane(CDCHandle dc)
+       {
+               RECT rect = { 0 };
+               GetClientRect(&rect);
+               if(IsVertical())
+                       rect.left += m_cxyHeader;
+               else
+                       rect.top += m_cxyHeader;
+               if((GetExStyle() & WS_EX_CLIENTEDGE) == 0)
+                       dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+               dc.FillRect(&rect, COLOR_APPWORKSPACE);
+       }
+
+       // drawing helper - draws "x" button image
+       void DrawButtonImage(CDCHandle dc, RECT& rcImage, HPEN hPen)
+       {
+#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+               HPEN hPenOld = dc.SelectPen(hPen);
+
+               dc.MoveTo(rcImage.left, rcImage.top);
+               dc.LineTo(rcImage.right, rcImage.bottom);
+               dc.MoveTo(rcImage.left + 1, rcImage.top);
+               dc.LineTo(rcImage.right + 1, rcImage.bottom);
+
+               dc.MoveTo(rcImage.left, rcImage.bottom - 1);
+               dc.LineTo(rcImage.right, rcImage.top - 1);
+               dc.MoveTo(rcImage.left + 1, rcImage.bottom - 1);
+               dc.LineTo(rcImage.right + 1, rcImage.top - 1);
+
+               dc.SelectPen(hPenOld);
+#else // (_WIN32_WCE < 400)
+               rcImage;
+               hPen;
+               // no support for the "x" button image
+#endif // (_WIN32_WCE < 400)
+       }
+
+       bool IsVertical() const
+       {
+               return ((m_dwExtendedStyle & PANECNT_VERTICAL) != 0);
+       }
+};
+
+class CPaneContainer : public CPaneContainerImpl<CPaneContainer>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("WTL_PaneContainer"), 0, -1)
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CSortListViewCtrl - implements sorting for a listview control
+
+// sort listview extended styles
+#define SORTLV_USESHELLBITMAPS 0x00000001
+
+// Notification sent to parent when sort column is changed by user clicking header.  
+#define SLVN_SORTCHANGED       LVN_LAST
+
+// A LPNMSORTLISTVIEW is sent with the SLVN_SORTCHANGED notification
+typedef struct tagNMSORTLISTVIEW
+{
+    NMHDR hdr;
+    int iNewSortColumn;
+    int iOldSortColumn;
+} NMSORTLISTVIEW, *LPNMSORTLISTVIEW;
+
+// Column sort types. Can be set on a per-column basis with the SetColumnSortType method.
+enum
+{
+       LVCOLSORT_NONE,
+       LVCOLSORT_TEXT,   // default
+       LVCOLSORT_TEXTNOCASE,
+       LVCOLSORT_LONG,
+       LVCOLSORT_DOUBLE,
+       LVCOLSORT_DECIMAL,
+       LVCOLSORT_DATETIME,
+       LVCOLSORT_DATE,
+       LVCOLSORT_TIME,
+       LVCOLSORT_CUSTOM,
+       LVCOLSORT_LAST = LVCOLSORT_CUSTOM
+};
+
+
+template <class T>
+class CSortListViewImpl
+{
+public:
+       enum
+       {
+               m_cchCmpTextMax = 32, // overrideable
+               m_cxSortImage = 16,
+               m_cySortImage = 15,
+               m_cxSortArrow = 11,
+               m_cySortArrow = 6,
+               m_iSortUp = 0,        // index of sort bitmaps
+               m_iSortDown = 1,
+               m_nShellSortUpID = 133
+       };
+
+       // passed to LVCompare functions as lParam1 and lParam2 
+       struct LVCompareParam
+       {
+               int iItem;
+               DWORD_PTR dwItemData;
+               union
+               {
+                       long lValue;
+                       double dblValue;
+                       DECIMAL decValue;
+                       LPCTSTR pszValue;
+               };
+       };
+       
+       // passed to LVCompare functions as the lParamSort parameter
+       struct LVSortInfo
+       {
+               T* pT;
+               int iSortCol;
+               bool bDescending;
+       };
+
+       bool m_bSortDescending;
+       bool m_bCommCtrl6;
+       int m_iSortColumn;
+       CBitmap m_bmSort[2];
+       int m_fmtOldSortCol;
+       HBITMAP m_hbmOldSortCol;
+       DWORD m_dwSortLVExtendedStyle;
+       ATL::CSimpleArray<WORD> m_arrColSortType;
+       bool m_bUseWaitCursor;
+       
+       CSortListViewImpl() :
+                       m_bSortDescending(false),
+                       m_bCommCtrl6(false),
+                       m_iSortColumn(-1), 
+                       m_fmtOldSortCol(0),
+                       m_hbmOldSortCol(NULL),
+                       m_dwSortLVExtendedStyle(SORTLV_USESHELLBITMAPS),
+                       m_bUseWaitCursor(true)
+       {
+#ifndef _WIN32_WCE
+               DWORD dwMajor = 0;
+               DWORD dwMinor = 0;
+               HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
+               m_bCommCtrl6 = SUCCEEDED(hRet) && dwMajor >= 6;
+#endif // !_WIN32_WCE
+       }
+       
+// Attributes
+       void SetSortColumn(int iCol)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               CHeaderCtrl header = pT->GetHeader();
+               ATLASSERT(header.m_hWnd != NULL);
+               ATLASSERT(iCol >= -1 && iCol < m_arrColSortType.GetSize());
+
+               int iOldSortCol = m_iSortColumn;
+               m_iSortColumn = iCol;
+               if(m_bCommCtrl6)
+               {
+#ifndef HDF_SORTUP
+                       const int HDF_SORTUP = 0x0400;  
+#endif // HDF_SORTUP
+#ifndef HDF_SORTDOWN
+                       const int HDF_SORTDOWN = 0x0200;        
+#endif // HDF_SORTDOWN
+                       const int nMask = HDF_SORTUP | HDF_SORTDOWN;
+                       HDITEM hditem = { HDI_FORMAT };
+                       if(iOldSortCol != iCol && iOldSortCol >= 0 && header.GetItem(iOldSortCol, &hditem))
+                       {
+                               hditem.fmt &= ~nMask;
+                               header.SetItem(iOldSortCol, &hditem);
+                       }
+                       if(iCol >= 0 && header.GetItem(iCol, &hditem))
+                       {
+                               hditem.fmt &= ~nMask;
+                               hditem.fmt |= m_bSortDescending ? HDF_SORTDOWN : HDF_SORTUP;
+                               header.SetItem(iCol, &hditem);
+                       }
+                       return;
+               }
+
+               if(m_bmSort[m_iSortUp].IsNull())
+                       pT->CreateSortBitmaps();
+
+               // restore previous sort column's bitmap, if any, and format
+               HDITEM hditem = { HDI_BITMAP | HDI_FORMAT };
+               if(iOldSortCol != iCol && iOldSortCol >= 0)
+               {
+                       hditem.hbm = m_hbmOldSortCol;
+                       hditem.fmt = m_fmtOldSortCol;
+                       header.SetItem(iOldSortCol, &hditem);
+               }
+
+               // save new sort column's bitmap and format, and add our sort bitmap
+               if(iCol >= 0 && header.GetItem(iCol, &hditem))
+               {
+                       if(iOldSortCol != iCol)
+                       {
+                               m_fmtOldSortCol = hditem.fmt;
+                               m_hbmOldSortCol = hditem.hbm;
+                       }
+                       hditem.fmt &= ~HDF_IMAGE;
+                       hditem.fmt |= HDF_BITMAP | HDF_BITMAP_ON_RIGHT;
+                       int i = m_bSortDescending ? m_iSortDown : m_iSortUp;
+                       hditem.hbm = m_bmSort[i];
+                       header.SetItem(iCol, &hditem);
+               }
+       }
+
+       int GetSortColumn() const
+       {
+               return m_iSortColumn;
+       }
+
+       void SetColumnSortType(int iCol, WORD wType)
+       {
+               ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize());
+               ATLASSERT(wType >= LVCOLSORT_NONE && wType <= LVCOLSORT_LAST);
+               m_arrColSortType[iCol] = wType;
+       }
+
+       WORD GetColumnSortType(int iCol) const
+       {
+               ATLASSERT((iCol >= 0) && iCol < m_arrColSortType.GetSize());
+               return m_arrColSortType[iCol];
+       }
+
+       int GetColumnCount() const
+       {
+               const T* pT = static_cast<const T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               CHeaderCtrl header = pT->GetHeader();
+               return header.m_hWnd != NULL ? header.GetItemCount() : 0;
+       }
+
+       bool IsSortDescending() const
+       {
+               return m_bSortDescending;
+       }
+
+       DWORD GetSortListViewExtendedStyle() const
+       {
+               return m_dwSortLVExtendedStyle;
+       }
+
+       DWORD SetSortListViewExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
+       {
+               DWORD dwPrevStyle = m_dwSortLVExtendedStyle;
+               if(dwMask == 0)
+                       m_dwSortLVExtendedStyle = dwExtendedStyle;
+               else
+                       m_dwSortLVExtendedStyle = (m_dwSortLVExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
+               return dwPrevStyle;
+       }
+
+// Operations
+       bool DoSortItems(int iCol, bool bDescending = false)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize());
+
+               WORD wType = m_arrColSortType[iCol];
+               if(wType == LVCOLSORT_NONE)
+                       return false;
+
+               int nCount = pT->GetItemCount();
+               if(nCount < 2)
+               {
+                       m_bSortDescending = bDescending;
+                       SetSortColumn(iCol);
+                       return true;
+               }
+
+               CWaitCursor waitCursor(false);
+               if(m_bUseWaitCursor)
+                       waitCursor.Set();
+
+               LVCompareParam* pParam = NULL;
+               ATLTRY(pParam = new LVCompareParam[nCount]);
+               PFNLVCOMPARE pFunc = NULL;
+               TCHAR pszTemp[pT->m_cchCmpTextMax];
+               bool bStrValue = false;
+
+               switch(wType)
+               {
+               case LVCOLSORT_TEXT:
+                       pFunc = (PFNLVCOMPARE)pT->LVCompareText;
+               case LVCOLSORT_TEXTNOCASE:
+                       if(pFunc == NULL)
+                               pFunc = (PFNLVCOMPARE)pT->LVCompareTextNoCase;
+               case LVCOLSORT_CUSTOM:
+                       {
+                               if(pFunc == NULL)
+                                       pFunc = (PFNLVCOMPARE)pT->LVCompareCustom;
+
+                               for(int i = 0; i < nCount; i++)
+                               {
+                                       pParam[i].iItem = i;
+                                       pParam[i].dwItemData = pT->GetItemData(i);
+                                       pParam[i].pszValue = new TCHAR[pT->m_cchCmpTextMax];
+                                       pT->GetItemText(i, iCol, (LPTSTR)pParam[i].pszValue, pT->m_cchCmpTextMax);
+                                       pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
+                               }
+                               bStrValue = true;
+                       }
+                       break;
+               case LVCOLSORT_LONG:
+                       {
+                               pFunc = (PFNLVCOMPARE)pT->LVCompareLong;
+                               for(int i = 0; i < nCount; i++)
+                               {
+                                       pParam[i].iItem = i;
+                                       pParam[i].dwItemData = pT->GetItemData(i);
+                                       pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
+                                       pParam[i].lValue = pT->StrToLong(pszTemp);
+                                       pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
+                               }
+                       }
+                       break;
+               case LVCOLSORT_DOUBLE:
+                       {
+                               pFunc = (PFNLVCOMPARE)pT->LVCompareDouble;
+                               for(int i = 0; i < nCount; i++)
+                               {
+                                       pParam[i].iItem = i;
+                                       pParam[i].dwItemData = pT->GetItemData(i);
+                                       pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
+                                       pParam[i].dblValue = pT->StrToDouble(pszTemp);
+                                       pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
+                               }
+                       }
+                       break;
+               case LVCOLSORT_DECIMAL:
+                       {
+                               pFunc = (PFNLVCOMPARE)pT->LVCompareDecimal;
+                               for(int i = 0; i < nCount; i++)
+                               {
+                                       pParam[i].iItem = i;
+                                       pParam[i].dwItemData = pT->GetItemData(i);
+                                       pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
+                                       pT->StrToDecimal(pszTemp, &pParam[i].decValue);
+                                       pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
+                               }
+                       }
+                       break;
+               case LVCOLSORT_DATETIME:
+               case LVCOLSORT_DATE:
+               case LVCOLSORT_TIME:
+                       {
+                               pFunc = (PFNLVCOMPARE)pT->LVCompareDouble;
+                               DWORD dwFlags = LOCALE_NOUSEROVERRIDE;
+                               if(wType == LVCOLSORT_DATE)
+                                       dwFlags |= VAR_DATEVALUEONLY;
+                               else if(wType == LVCOLSORT_TIME)
+                                       dwFlags |= VAR_TIMEVALUEONLY;
+                               for(int i = 0; i < nCount; i++)
+                               {
+                                       pParam[i].iItem = i;
+                                       pParam[i].dwItemData = pT->GetItemData(i);
+                                       pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
+                                       pParam[i].dblValue = pT->DateStrToDouble(pszTemp, dwFlags);
+                                       pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
+                               }
+                       }
+                       break;
+               default:
+                       ATLTRACE2(atlTraceUI, 0, _T("Unknown value for sort type in CSortListViewImpl::DoSortItems()\n"));
+                       break;
+               } // switch(wType)
+
+               ATLASSERT(pFunc != NULL);
+               LVSortInfo lvsi = { pT, iCol, bDescending };
+               bool bRet = ((BOOL)pT->DefWindowProc(LVM_SORTITEMS, (WPARAM)&lvsi, (LPARAM)pFunc) != FALSE);
+               for(int i = 0; i < nCount; i++)
+               {
+                       DWORD_PTR dwItemData = pT->GetItemData(i);
+                       LVCompareParam* p = (LVCompareParam*)dwItemData;
+                       ATLASSERT(p != NULL);
+                       if(bStrValue)
+                               delete [] (TCHAR*)p->pszValue;
+                       pT->SetItemData(i, p->dwItemData);
+               }
+               delete [] pParam;
+
+               if(bRet)
+               {
+                       m_bSortDescending = bDescending;
+                       SetSortColumn(iCol);
+               }
+
+               if(m_bUseWaitCursor)
+                       waitCursor.Restore();
+
+               return bRet;
+       }
+
+       void CreateSortBitmaps()
+       {
+               if((m_dwSortLVExtendedStyle & SORTLV_USESHELLBITMAPS) != 0)
+               {
+                       bool bFree = false;
+                       LPCTSTR pszModule = _T("shell32.dll"); 
+                       HINSTANCE hShell = ::GetModuleHandle(pszModule);
+
+                       if (hShell == NULL)             
+                       {
+                               hShell = ::LoadLibrary(pszModule);
+                               bFree = true;
+                       }
+                       if (hShell != NULL)
+                       {
+                               bool bSuccess = true;
+                               for(int i = m_iSortUp; i <= m_iSortDown; i++)
+                               {
+                                       if(!m_bmSort[i].IsNull())
+                                               m_bmSort[i].DeleteObject();
+                                       m_bmSort[i] = (HBITMAP)::LoadImage(hShell, MAKEINTRESOURCE(m_nShellSortUpID + i), 
+#ifndef _WIN32_WCE
+                                               IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+#else // CE specific
+                                               IMAGE_BITMAP, 0, 0, 0);
+#endif // _WIN32_WCE
+                                       if(m_bmSort[i].IsNull())
+                                       {
+                                               bSuccess = false;
+                                               break;
+                                       }
+                               }
+                               if(bFree)
+                                       ::FreeLibrary(hShell);
+                               if(bSuccess)
+                                       return;
+                       }
+               }
+
+               T* pT = static_cast<T*>(this);
+               for(int i = m_iSortUp; i <= m_iSortDown; i++)
+               {
+                       if(!m_bmSort[i].IsNull())
+                               m_bmSort[i].DeleteObject();
+
+                       CDC dcMem;
+                       CClientDC dc(::GetDesktopWindow());
+                       dcMem.CreateCompatibleDC(dc.m_hDC);
+                       m_bmSort[i].CreateCompatibleBitmap(dc.m_hDC, m_cxSortImage, m_cySortImage);
+                       HBITMAP hbmOld = dcMem.SelectBitmap(m_bmSort[i]);
+                       RECT rc = {0,0,m_cxSortImage, m_cySortImage};
+                       pT->DrawSortBitmap(dcMem.m_hDC, i, &rc);
+                       dcMem.SelectBitmap(hbmOld);
+                       dcMem.DeleteDC();
+               }
+       }
+
+       void NotifyParentSortChanged(int iNewSortCol, int iOldSortCol)
+       {
+               T* pT = static_cast<T*>(this);
+               int nID = pT->GetDlgCtrlID();
+               NMSORTLISTVIEW nm = { { pT->m_hWnd, nID, SLVN_SORTCHANGED }, iNewSortCol, iOldSortCol };
+               ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nID, (LPARAM)&nm);
+       }
+
+// Overrideables
+       int CompareItemsCustom(LVCompareParam* /*pItem1*/, LVCompareParam* /*pItem2*/, int /*iSortCol*/)
+       {
+               // pItem1 and pItem2 contain valid iItem, dwItemData, and pszValue members.
+               // If item1 > item2 return 1, if item1 < item2 return -1, else return 0.
+               return 0;
+       }
+
+       void DrawSortBitmap(CDCHandle dc, int iBitmap, LPRECT prc)
+       {
+               dc.FillRect(prc, ::GetSysColorBrush(COLOR_BTNFACE));    
+               HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
+               CPen pen;
+               pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNSHADOW));
+               HPEN hpenOld = dc.SelectPen(pen);
+               POINT ptOrg = { (m_cxSortImage - m_cxSortArrow) / 2, (m_cySortImage - m_cySortArrow) / 2 };
+               if(iBitmap == m_iSortUp)
+               {
+                       POINT pts[3] = 
+                       {
+                               { ptOrg.x + m_cxSortArrow / 2, ptOrg.y },
+                               { ptOrg.x, ptOrg.y + m_cySortArrow - 1 }, 
+                               { ptOrg.x + m_cxSortArrow - 1, ptOrg.y + m_cySortArrow - 1 }
+                       };
+                       dc.Polygon(pts, 3);
+               }
+               else
+               {
+                       POINT pts[3] = 
+                       {
+                               { ptOrg.x, ptOrg.y },
+                               { ptOrg.x + m_cxSortArrow / 2, ptOrg.y + m_cySortArrow - 1 },
+                               { ptOrg.x + m_cxSortArrow - 1, ptOrg.y }
+                       };
+                       dc.Polygon(pts, 3);
+               }
+               dc.SelectBrush(hbrOld);
+               dc.SelectPen(hpenOld);
+       }
+
+       double DateStrToDouble(LPCTSTR lpstr, DWORD dwFlags)
+       {
+               ATLASSERT(lpstr != NULL);
+               if(lpstr == NULL || lpstr[0] == _T('\0'))
+                       return 0;
+
+               USES_CONVERSION;
+               HRESULT hRet = E_FAIL;
+               DATE dRet = 0;
+               if (FAILED(hRet = ::VarDateFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, dwFlags, &dRet)))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("VarDateFromStr failed with result of 0x%8.8X\n"), hRet);
+                       dRet = 0;
+               }
+               return dRet;
+       }
+
+       long StrToLong(LPCTSTR lpstr)
+       {
+               ATLASSERT(lpstr != NULL);
+               if(lpstr == NULL || lpstr[0] == _T('\0'))
+                       return 0;
+               
+               USES_CONVERSION;
+               HRESULT hRet = E_FAIL;
+               long lRet = 0;
+               if (FAILED(hRet = ::VarI4FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &lRet)))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("VarI4FromStr failed with result of 0x%8.8X\n"), hRet);
+                       lRet = 0;
+               }
+               return lRet;
+       }
+
+       double StrToDouble(LPCTSTR lpstr)
+       {
+               ATLASSERT(lpstr != NULL);
+               if(lpstr == NULL || lpstr[0] == _T('\0'))
+                       return 0;
+
+               USES_CONVERSION;
+               HRESULT hRet = E_FAIL;
+               double dblRet = 0;
+               if (FAILED(hRet = ::VarR8FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &dblRet)))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("VarR8FromStr failed with result of 0x%8.8X\n"), hRet);
+                       dblRet = 0;
+               }
+               return dblRet;
+       }
+
+       bool StrToDecimal(LPCTSTR lpstr, DECIMAL* pDecimal)
+       {
+               ATLASSERT(lpstr != NULL);
+               ATLASSERT(pDecimal != NULL);
+               if(lpstr == NULL || pDecimal == NULL)
+                       return false;
+
+               USES_CONVERSION;
+               HRESULT hRet = E_FAIL;
+               if (FAILED(hRet = ::VarDecFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, pDecimal)))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("VarDecFromStr failed with result of 0x%8.8X\n"), hRet);
+                       pDecimal->Lo64 = 0;
+                       pDecimal->Hi32 = 0;
+                       pDecimal->signscale = 0;
+                       return false;
+               }
+               return true;
+       }
+
+// Overrideable PFNLVCOMPARE functions
+       static int CALLBACK LVCompareText(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+       {
+               ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
+
+               LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
+               LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
+               LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
+               
+               int nRet = lstrcmp(pParam1->pszValue, pParam2->pszValue);
+               return pInfo->bDescending ? -nRet : nRet;
+       }
+
+       static int CALLBACK LVCompareTextNoCase(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+       {
+               ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
+
+               LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
+               LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
+               LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
+               
+               int nRet = lstrcmpi(pParam1->pszValue, pParam2->pszValue);
+               return pInfo->bDescending ? -nRet : nRet;
+       }
+
+       static int CALLBACK LVCompareLong(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+       {
+               ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
+
+               LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
+               LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
+               LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
+               
+               int nRet = 0;
+               if(pParam1->lValue > pParam2->lValue)
+                       nRet = 1;
+               else if(pParam1->lValue < pParam2->lValue)
+                       nRet = -1;
+               return pInfo->bDescending ? -nRet : nRet;
+       }
+
+       static int CALLBACK LVCompareDouble(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+       {
+               ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
+
+               LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
+               LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
+               LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
+               
+               int nRet = 0;
+               if(pParam1->dblValue > pParam2->dblValue)
+                       nRet = 1;
+               else if(pParam1->dblValue < pParam2->dblValue)
+                       nRet = -1;
+               return pInfo->bDescending ? -nRet : nRet;
+       }
+
+       static int CALLBACK LVCompareCustom(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+       {
+               ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
+
+               LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
+               LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
+               LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
+               
+               int nRet = pInfo->pT->CompareItemsCustom(pParam1, pParam2, pInfo->iSortCol);
+               return pInfo->bDescending ? -nRet : nRet;
+       }
+
+#ifndef _WIN32_WCE
+       static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+       {
+               ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
+
+               LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
+               LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
+               LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
+               
+               int nRet = (int)::VarDecCmp(&pParam1->decValue, &pParam2->decValue);
+               nRet--;
+               return pInfo->bDescending ? -nRet : nRet;
+       }
+#else
+       // Compare mantissas, ignore sign and scale
+       static int CompareMantissas(const DECIMAL& decLeft, const DECIMAL& decRight)
+       {
+               if (decLeft.Hi32 < decRight.Hi32)
+               {
+                       return -1;
+               }
+               if (decLeft.Hi32 > decRight.Hi32)
+               {
+                       return 1;
+               }
+               // Here, decLeft.Hi32 == decRight.Hi32
+               if (decLeft.Lo64 < decRight.Lo64)
+               {
+                       return -1;
+               }
+               if (decLeft.Lo64 > decRight.Lo64)
+               {
+                       return 1;
+               }
+               return 0;
+       }
+
+       // return values: VARCMP_LT, VARCMP_EQ, VARCMP_GT, VARCMP_NULL
+       static HRESULT VarDecCmp(const DECIMAL* pdecLeft, const DECIMAL* pdecRight)
+       {
+               static const ULONG powersOfTen[] =
+               {
+                       10ul,
+                       100ul,
+                       1000ul,
+                       10000ul,
+                       100000ul,
+                       1000000ul,
+                       10000000ul,
+                       100000000ul,
+                       1000000000ul
+               };
+               static const int largestPower = sizeof(powersOfTen) / sizeof(powersOfTen[0]);
+               if (!pdecLeft || !pdecRight)
+               {
+                       return VARCMP_NULL;
+               }
+               
+               // Degenerate case - at least one comparand is of the form
+               // [+-]0*10^N (denormalized zero)
+               bool bLeftZero = (!pdecLeft->Lo64 && !pdecLeft->Hi32);
+               bool bRightZero = (!pdecRight->Lo64 && !pdecRight->Hi32);
+               if (bLeftZero && bRightZero)
+               {
+                       return VARCMP_EQ;
+               }
+               bool bLeftNeg = ((pdecLeft->sign & DECIMAL_NEG) != 0);
+               bool bRightNeg = ((pdecRight->sign & DECIMAL_NEG) != 0);
+               if (bLeftZero)
+               {
+                       return (bRightNeg ? VARCMP_GT : VARCMP_LT);
+               }
+               // This also covers the case where the comparands have different signs
+               if (bRightZero || bLeftNeg != bRightNeg)
+               {
+                       return (bLeftNeg ? VARCMP_LT : VARCMP_GT);
+               }
+
+               // Here both comparands have the same sign and need to be compared
+               // on mantissa and scale. The result is obvious when
+               // 1. Scales are equal (then compare mantissas)
+               // 2. A number with smaller scale is also the one with larger mantissa
+               //    (then this number is obviously larger)
+               // In the remaining case, we would multiply the number with smaller
+               // scale by 10 and simultaneously increment its scale (which amounts to
+               // adding trailing zeros after decimal point), until the numbers fall under
+               // one of the two cases above
+               DECIMAL temp;
+               bool bInvert = bLeftNeg; // the final result needs to be inverted
+               if (pdecLeft->scale < pdecRight->scale)
+               {
+                       temp = *pdecLeft;
+               }
+               else
+               {
+                       temp = *pdecRight;
+                       pdecRight = pdecLeft;
+                       bInvert = !bInvert;
+               }
+
+               // Now temp is the number with smaller (or equal) scale, and
+               // we can modify it freely without touching original parameters
+               int comp;
+               while ((comp = CompareMantissas(temp, *pdecRight)) < 0 &&
+                       temp.scale < pdecRight->scale)
+               {
+                       // Multiply by an appropriate power of 10
+                       int scaleDiff = pdecRight->scale - temp.scale;
+                       if (scaleDiff > largestPower)
+                       {
+                               // Keep the multiplier representable in 32bit
+                               scaleDiff = largestPower;
+                       }
+                       DWORDLONG power = powersOfTen[scaleDiff - 1];
+                       // Multiply temp's mantissa by power
+                       DWORDLONG product = temp.Lo32 * power;
+                       ULONG carry = static_cast<ULONG>(product >> 32);
+                       temp.Lo32  = static_cast<ULONG>(product);
+                       product = temp.Mid32 * power + carry;
+                       carry = static_cast<ULONG>(product >> 32);
+                       temp.Mid32 = static_cast<ULONG>(product);
+                       product = temp.Hi32 * power + carry;
+                       if (static_cast<ULONG>(product >> 32))
+                       {
+                               // Multiplication overflowed - pdecLeft is clearly larger
+                               break;
+                       }
+                       temp.Hi32 = static_cast<ULONG>(product);
+                       temp.scale = (BYTE)(temp.scale + scaleDiff);
+               }
+               if (temp.scale < pdecRight->scale)
+               {
+                       comp = 1;
+               }
+               if (bInvert)
+               {
+                       comp = -comp;
+               }
+               return (comp > 0 ? VARCMP_GT : comp < 0 ? VARCMP_LT : VARCMP_EQ);
+       }
+
+       static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+       {
+               ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
+
+               LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
+               LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
+               LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
+               
+               int nRet = (int)VarDecCmp(&pParam1->decValue, &pParam2->decValue);
+               nRet--;
+               return pInfo->bDescending ? -nRet : nRet;
+       }
+#endif // !_WIN32_WCE
+
+       BEGIN_MSG_MAP(CSortListViewImpl)
+               MESSAGE_HANDLER(LVM_INSERTCOLUMN, OnInsertColumn)
+               MESSAGE_HANDLER(LVM_DELETECOLUMN, OnDeleteColumn)
+               NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, OnHeaderItemClick)
+               NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, OnHeaderItemClick)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+       END_MSG_MAP()
+
+       LRESULT OnInsertColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)     
+       {
+               T* pT = static_cast<T*>(this);
+               LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
+               if(lRet == -1)
+                       return -1;
+
+               WORD wType = 0;
+               m_arrColSortType.Add(wType);
+               int nCount = m_arrColSortType.GetSize();
+               ATLASSERT(nCount == GetColumnCount());
+
+               for(int i = nCount - 1; i > lRet; i--)
+                       m_arrColSortType[i] = m_arrColSortType[i - 1];
+               m_arrColSortType[(int)lRet] = LVCOLSORT_TEXT;
+
+               if(lRet <= m_iSortColumn)
+                       m_iSortColumn++;
+
+               return lRet;
+       }
+
+       LRESULT OnDeleteColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)     
+       {
+               T* pT = static_cast<T*>(this);
+               LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
+               if(lRet == 0)
+                       return 0;
+
+               int iCol = (int)wParam; 
+               if(m_iSortColumn == iCol)
+                       m_iSortColumn = -1;
+               else if(m_iSortColumn > iCol)
+                       m_iSortColumn--;
+               m_arrColSortType.RemoveAt(iCol);
+
+               return lRet;
+       }
+
+       LRESULT OnHeaderItemClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               LPNMHEADER p = (LPNMHEADER)pnmh;
+               if(p->iButton == 0)
+               {
+                       int iOld = m_iSortColumn;
+                       bool bDescending = (m_iSortColumn == p->iItem) ? !m_bSortDescending : false;
+                       if(DoSortItems(p->iItem, bDescending))
+                               NotifyParentSortChanged(p->iItem, iOld);                                
+               }
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifndef _WIN32_WCE
+               if(wParam == SPI_SETNONCLIENTMETRICS)
+                       GetSystemSettings();
+#else  // CE specific
+               wParam; // avoid level 4 warning
+               GetSystemSettings();
+#endif // _WIN32_WCE
+               bHandled = FALSE;
+               return 0;
+       }
+
+       void GetSystemSettings()
+       {
+               if(!m_bCommCtrl6 && !m_bmSort[m_iSortUp].IsNull())
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->CreateSortBitmaps();
+                       if(m_iSortColumn != -1)
+                               SetSortColumn(m_iSortColumn);
+               }
+       }
+
+};
+
+
+typedef ATL::CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | LVS_REPORT | LVS_SHOWSELALWAYS , WS_EX_CLIENTEDGE>   CSortListViewCtrlTraits;
+
+template <class T, class TBase = CListViewCtrl, class TWinTraits = CSortListViewCtrlTraits>
+class ATL_NO_VTABLE CSortListViewCtrlImpl: public ATL::CWindowImpl<T, TBase, TWinTraits>, public CSortListViewImpl<T>
+{
+public:
+       DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
+
+       bool SortItems(int iCol, bool bDescending = false)
+       {
+               return DoSortItems(iCol, bDescending);
+       }
+               
+       BEGIN_MSG_MAP(CSortListViewCtrlImpl)
+               MESSAGE_HANDLER(LVM_INSERTCOLUMN, CSortListViewImpl<T>::OnInsertColumn)
+               MESSAGE_HANDLER(LVM_DELETECOLUMN, CSortListViewImpl<T>::OnDeleteColumn)
+               NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, CSortListViewImpl<T>::OnHeaderItemClick)
+               NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, CSortListViewImpl<T>::OnHeaderItemClick)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, CSortListViewImpl<T>::OnSettingChange)
+       END_MSG_MAP()
+};
+
+class CSortListViewCtrl : public CSortListViewCtrlImpl<CSortListViewCtrl>
+{
+public:
+       DECLARE_WND_SUPERCLASS(_T("WTL_SortListViewCtrl"), GetWndClassName())
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTabView - implements tab view window
+
+// TabView Notifications
+#define TBVN_PAGEACTIVATED   (0U-741)
+#define TBVN_CONTEXTMENU     (0U-742)
+
+// Notification data for TBVN_CONTEXTMENU
+struct TBVCONTEXTMENUINFO
+{
+       NMHDR hdr;
+       POINT pt;
+};
+
+typedef TBVCONTEXTMENUINFO* LPTBVCONTEXTMENUINFO;
+
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CTabViewImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>
+{
+public:
+       DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE)
+
+// Declarations and enums
+       struct TABVIEWPAGE
+       {
+               HWND hWnd;
+               LPTSTR lpstrTitle;
+               LPVOID pData;
+       };
+
+       struct TCITEMEXTRA
+       {
+               TCITEMHEADER tciheader;
+               TABVIEWPAGE tvpage;
+
+               operator LPTCITEM() { return (LPTCITEM)this; }
+       };
+
+       enum
+       {
+               m_nTabID = 1313,
+               m_cxMoveMark = 6,
+               m_cyMoveMark = 3,
+               m_nMenuItemsMax = (ID_WINDOW_TABLAST - ID_WINDOW_TABFIRST + 1)
+       };
+
+// Data members
+       ATL::CContainedWindowT<CTabCtrl> m_tab;
+       int m_cyTabHeight;
+
+       int m_nActivePage;
+
+       int m_nInsertItem;
+       POINT m_ptStartDrag;
+
+       CMenuHandle m_menu;
+
+       int m_cchTabTextLength;
+
+       int m_nMenuItemsCount;
+
+       ATL::CWindow m_wndTitleBar;
+       LPTSTR m_lpstrTitleBarBase;
+       int m_cchTitleBarLength;
+
+       CImageList m_ilDrag;
+
+       bool m_bDestroyPageOnRemove:1;
+       bool m_bDestroyImageList:1;
+       bool m_bActivePageMenuItem:1;
+       bool m_bActiveAsDefaultMenuItem:1;
+       bool m_bEmptyMenuItem:1;
+       bool m_bWindowsMenuItem:1;
+       // internal
+       bool m_bTabCapture:1;
+       bool m_bTabDrag:1;
+
+// Constructor/destructor
+       CTabViewImpl() :
+                       m_nActivePage(-1), 
+                       m_cyTabHeight(0), 
+                       m_tab(this, 1), 
+                       m_nInsertItem(-1), 
+                       m_cchTabTextLength(30), 
+                       m_nMenuItemsCount(10), 
+                       m_lpstrTitleBarBase(NULL), 
+                       m_cchTitleBarLength(100), 
+                       m_bDestroyPageOnRemove(true), 
+                       m_bDestroyImageList(true), 
+                       m_bActivePageMenuItem(true), 
+                       m_bActiveAsDefaultMenuItem(false), 
+                       m_bEmptyMenuItem(false), 
+                       m_bWindowsMenuItem(false), 
+                       m_bTabCapture(false), 
+                       m_bTabDrag(false)
+       {
+               m_ptStartDrag.x = 0;
+               m_ptStartDrag.y = 0;
+       }
+
+       ~CTabViewImpl()
+       {
+               delete [] m_lpstrTitleBarBase;
+       }
+
+// Message filter function - to be called from PreTranslateMessage of the main window
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if(IsWindow() == FALSE)
+                       return FALSE;
+
+               BOOL bRet = FALSE;
+
+               // Check for TabView built-in accelerators (Ctrl+Tab/Ctrl+Shift+Tab - next/previous page)
+               int nCount = GetPageCount();
+               if(nCount > 0)
+               {
+                       bool bControl = (::GetKeyState(VK_CONTROL) < 0);
+                       if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB) && bControl)
+                       {
+                               if(nCount > 1)
+                               {
+                                       int nPage = m_nActivePage;
+                                       bool bShift = (::GetKeyState(VK_SHIFT) < 0);
+                                       if(bShift)
+                                               nPage = (nPage > 0) ? (nPage - 1) : (nCount - 1);
+                                       else
+                                               nPage = ((nPage >= 0) && (nPage < (nCount - 1))) ? (nPage + 1) : 0;
+
+                                       SetActivePage(nPage);
+                                       T* pT = static_cast<T*>(this);
+                                       pT->OnPageActivated(m_nActivePage);
+                               }
+
+                               bRet = TRUE;
+                       }
+               }
+
+               // If we are doing drag-drop, check for Escape key that cancels it
+               if(bRet == FALSE)
+               {
+                       if(m_bTabCapture && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
+                       {
+                               ::ReleaseCapture();
+                               bRet = TRUE;
+                       }
+               }
+
+               // Pass the message to the active page
+               if(bRet == FALSE)
+               {
+                       if(m_nActivePage != -1)
+                               bRet = (BOOL)::SendMessage(GetPageHWND(m_nActivePage), WM_FORWARDMSG, 0, (LPARAM)pMsg);
+               }
+
+               return bRet;
+       }
+
+// Attributes
+       int GetPageCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return m_tab.GetItemCount();
+       }
+
+       int GetActivePage() const
+       {
+               return m_nActivePage;
+       }
+
+       void SetActivePage(int nPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               T* pT = static_cast<T*>(this);
+
+               SetRedraw(FALSE);
+
+               if(m_nActivePage != -1)
+                       ::ShowWindow(GetPageHWND(m_nActivePage), FALSE);
+               m_nActivePage = nPage;
+               m_tab.SetCurSel(m_nActivePage);
+               ::ShowWindow(GetPageHWND(m_nActivePage), TRUE);
+
+               pT->UpdateLayout();
+
+               SetRedraw(TRUE);
+               RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
+
+               if(::GetFocus() != m_tab.m_hWnd)
+                       ::SetFocus(GetPageHWND(m_nActivePage));
+
+               pT->UpdateTitleBar();
+               pT->UpdateMenu();
+       }
+
+       HIMAGELIST GetImageList() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return m_tab.GetImageList();
+       }
+
+       HIMAGELIST SetImageList(HIMAGELIST hImageList)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return m_tab.SetImageList(hImageList);
+       }
+
+       void SetWindowMenu(HMENU hMenu)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               m_menu = hMenu;
+
+               T* pT = static_cast<T*>(this);
+               pT->UpdateMenu();
+       }
+
+       void SetTitleBarWindow(HWND hWnd)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               delete [] m_lpstrTitleBarBase;
+               m_lpstrTitleBarBase = NULL;
+
+               m_wndTitleBar = hWnd;
+               if(hWnd == NULL)
+                       return;
+
+               int cchLen = m_wndTitleBar.GetWindowTextLength() + 1;
+               ATLTRY(m_lpstrTitleBarBase = new TCHAR[cchLen]);
+               if(m_lpstrTitleBarBase != NULL)
+               {
+                       m_wndTitleBar.GetWindowText(m_lpstrTitleBarBase, cchLen);
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateTitleBar();
+               }
+       }
+
+// Page attributes
+       HWND GetPageHWND(int nPage) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_PARAM;
+               m_tab.GetItem(nPage, tcix);
+
+               return tcix.tvpage.hWnd;
+       }
+
+       LPCTSTR GetPageTitle(int nPage) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_PARAM;
+               if(m_tab.GetItem(nPage, tcix) == FALSE)
+                       return NULL;
+
+               return tcix.tvpage.lpstrTitle;
+       }
+
+       bool SetPageTitle(int nPage, LPCTSTR lpstrTitle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               T* pT = static_cast<T*>(this);
+
+               int cchBuff = lstrlen(lpstrTitle) + 1;
+               LPTSTR lpstrBuff = NULL;
+               ATLTRY(lpstrBuff = new TCHAR[cchBuff]);
+               if(lpstrBuff == NULL)
+                       return false;
+
+               SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle);
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_PARAM;
+               if(m_tab.GetItem(nPage, tcix) == FALSE)
+                       return false;
+
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
+               if(lpstrTabText == NULL)
+                       return false;
+
+               delete [] tcix.tvpage.lpstrTitle;
+
+               pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1);
+
+               tcix.tciheader.mask = TCIF_TEXT | TCIF_PARAM;
+               tcix.tciheader.pszText = lpstrTabText;
+               tcix.tvpage.lpstrTitle = lpstrBuff;
+               if(m_tab.SetItem(nPage, tcix) == FALSE)
+                       return false;
+
+               pT->UpdateTitleBar();
+               pT->UpdateMenu();
+
+               return true;
+       }
+
+       LPVOID GetPageData(int nPage) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_PARAM;
+               m_tab.GetItem(nPage, tcix);
+
+               return tcix.tvpage.pData;
+       }
+
+       LPVOID SetPageData(int nPage, LPVOID pData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_PARAM;
+               m_tab.GetItem(nPage, tcix);
+               LPVOID pDataOld = tcix.tvpage.pData;
+
+               tcix.tvpage.pData = pData;
+               m_tab.SetItem(nPage, tcix);
+
+               return pDataOld;
+       }
+
+       int GetPageImage(int nPage) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_IMAGE;
+               m_tab.GetItem(nPage, tcix);
+
+               return tcix.tciheader.iImage;
+       }
+
+       int SetPageImage(int nPage, int nImage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_IMAGE;
+               m_tab.GetItem(nPage, tcix);
+               int nImageOld = tcix.tciheader.iImage;
+
+               tcix.tciheader.iImage = nImage;
+               m_tab.SetItem(nPage, tcix);
+
+               return nImageOld;
+       }
+
+// Operations
+       bool AddPage(HWND hWndView, LPCTSTR lpstrTitle, int nImage = -1, LPVOID pData = NULL)
+       {
+               return InsertPage(GetPageCount(), hWndView, lpstrTitle, nImage, pData);
+       }
+
+       bool InsertPage(int nPage, HWND hWndView, LPCTSTR lpstrTitle, int nImage = -1, LPVOID pData = NULL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(nPage == GetPageCount() || IsValidPageIndex(nPage));
+
+               T* pT = static_cast<T*>(this);
+
+               int cchBuff = lstrlen(lpstrTitle) + 1;
+               LPTSTR lpstrBuff = NULL;
+               ATLTRY(lpstrBuff = new TCHAR[cchBuff]);
+               if(lpstrBuff == NULL)
+                       return false;
+
+               SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle);
+
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
+               if(lpstrTabText == NULL)
+                       return false;
+
+               pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1);
+
+               SetRedraw(FALSE);
+
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
+               tcix.tciheader.pszText = lpstrTabText;
+               tcix.tciheader.iImage = nImage;
+               tcix.tvpage.hWnd = hWndView;
+               tcix.tvpage.lpstrTitle = lpstrBuff;
+               tcix.tvpage.pData = pData;
+               int nItem = m_tab.InsertItem(nPage, tcix);
+               if(nItem == -1)
+               {
+                       delete [] lpstrBuff;
+                       SetRedraw(TRUE);
+                       return false;
+               }
+
+               SetActivePage(nItem);
+               pT->OnPageActivated(m_nActivePage);
+
+               if(GetPageCount() == 1)
+                       pT->ShowTabControl(true);
+
+               pT->UpdateLayout();
+
+               SetRedraw(TRUE);
+               RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
+
+               return true;
+       }
+
+       void RemovePage(int nPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(IsValidPageIndex(nPage));
+
+               T* pT = static_cast<T*>(this);
+
+               SetRedraw(FALSE);
+
+               if(GetPageCount() == 1)
+                       pT->ShowTabControl(false);
+
+               if(m_bDestroyPageOnRemove)
+                       ::DestroyWindow(GetPageHWND(nPage));
+               else
+                       ::ShowWindow(GetPageHWND(nPage), FALSE);
+               LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(nPage);
+               delete [] lpstrTitle;
+
+               ATLVERIFY(m_tab.DeleteItem(nPage) != FALSE);
+
+               if(m_nActivePage == nPage)
+               {
+                       m_nActivePage = -1;
+
+                       if(nPage > 0)
+                       {
+                               SetActivePage(nPage - 1);
+                       }
+                       else if(GetPageCount() > 0)
+                       {
+                               SetActivePage(nPage);
+                       }
+                       else
+                       {
+                               SetRedraw(TRUE);
+                               Invalidate();
+                               UpdateWindow();
+                               pT->UpdateTitleBar();
+                               pT->UpdateMenu();
+                       }
+               }
+               else
+               {
+                       nPage = (nPage < m_nActivePage) ? (m_nActivePage - 1) : m_nActivePage;
+                       m_nActivePage = -1;
+                       SetActivePage(nPage);
+               }
+
+               pT->OnPageActivated(m_nActivePage);
+       }
+
+       void RemoveAllPages()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               if(GetPageCount() == 0)
+                       return;
+
+               T* pT = static_cast<T*>(this);
+
+               SetRedraw(FALSE);
+
+               pT->ShowTabControl(false);
+
+               for(int i = 0; i < GetPageCount(); i++)
+               {
+                       if(m_bDestroyPageOnRemove)
+                               ::DestroyWindow(GetPageHWND(i));
+                       else
+                               ::ShowWindow(GetPageHWND(i), FALSE);
+                       LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(i);
+                       delete [] lpstrTitle;
+               }
+               m_tab.DeleteAllItems();
+
+               m_nActivePage = -1;
+               pT->OnPageActivated(m_nActivePage);
+
+               SetRedraw(TRUE);
+               Invalidate();
+               UpdateWindow();
+
+               pT->UpdateTitleBar();
+               pT->UpdateMenu();
+       }
+
+       int PageIndexFromHwnd(HWND hWnd) const
+       {
+               int nIndex = -1;
+
+               for(int i = 0; i < GetPageCount(); i++)
+               {
+                       if(GetPageHWND(i) == hWnd)
+                       {
+                               nIndex = i;
+                               break;
+                       }
+               }
+
+               return nIndex;
+       }
+
+       void BuildWindowMenu(HMENU hMenu, int nMenuItemsCount = 10, bool bEmptyMenuItem = true, bool bWindowsMenuItem = true, bool bActivePageMenuItem = true, bool bActiveAsDefaultMenuItem = false)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               CMenuHandle menu = hMenu;
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+               int nFirstPos = 0;
+
+               // Find first menu item in our range
+#ifndef _WIN32_WCE
+               for(nFirstPos = 0; nFirstPos < menu.GetMenuItemCount(); nFirstPos++)
+               {
+                       UINT nID = menu.GetMenuItemID(nFirstPos);
+                       if((nID >= ID_WINDOW_TABFIRST && nID <= ID_WINDOW_TABLAST) || nID == ID_WINDOW_SHOWTABLIST)
+                               break;
+               }
+#else // CE specific
+               for(nFirstPos = 0; ; nFirstPos++)
+               {
+                       CMenuItemInfo mii;
+                       mii.fMask = MIIM_ID;
+                       BOOL bRet = menu.GetMenuItemInfo(nFirstPos, TRUE, &mii);
+                       if(bRet == FALSE)
+                               break;
+                       if((mii.wID >= ID_WINDOW_TABFIRST && mii.wID <= ID_WINDOW_TABLAST) || mii.wID == ID_WINDOW_SHOWTABLIST)
+                               break;
+               }
+#endif // _WIN32_WCE
+
+               // Remove all menu items for tab pages
+               BOOL bRet = TRUE;
+               while(bRet != FALSE)
+                       bRet = menu.DeleteMenu(nFirstPos, MF_BYPOSITION);
+
+               // Add separator if it's not already there
+               int nPageCount = GetPageCount();
+               if((bWindowsMenuItem || (nPageCount > 0)) && (nFirstPos > 0))
+               {
+                       CMenuItemInfo mii;
+                       mii.fMask = MIIM_TYPE;
+                       menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii);
+                       if((nFirstPos <= 0) || ((mii.fType & MFT_SEPARATOR) == 0))
+                       {
+                               menu.AppendMenu(MF_SEPARATOR);
+                               nFirstPos++;
+                       }
+               }
+
+               // Add menu items for all pages
+               if(nPageCount > 0)
+               {
+                       // Append menu items for all pages
+                       const int cchPrefix = 3;   // 2 digits + space
+                       nMenuItemsCount = min(min(nPageCount, nMenuItemsCount), (int)m_nMenuItemsMax);
+                       ATLASSERT(nMenuItemsCount < 100);   // 2 digits only
+                       if(nMenuItemsCount >= 100)
+                               nMenuItemsCount = 99;
+
+                       for(int i = 0; i < nMenuItemsCount; i++)
+                       {
+                               LPCTSTR lpstrTitle = GetPageTitle(i);
+                               int nLen = lstrlen(lpstrTitle);
+                               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+                               LPTSTR lpstrText = buff.Allocate(cchPrefix + nLen + 1);
+                               ATLASSERT(lpstrText != NULL);
+                               if(lpstrText != NULL)
+                               {
+                                       LPCTSTR lpstrFormat = (i < 9) ? _T("&%i %s") : _T("%i %s");
+                                       SecureHelper::wsprintf_x(lpstrText, cchPrefix + nLen + 1, lpstrFormat, i + 1, lpstrTitle);
+                                       menu.AppendMenu(MF_STRING, ID_WINDOW_TABFIRST + i, lpstrText);
+                               }
+                       }
+
+                       // Mark active page
+                       if(bActivePageMenuItem && (m_nActivePage != -1))
+                       {
+#ifndef _WIN32_WCE
+                               if(bActiveAsDefaultMenuItem)
+                               {
+                                       menu.SetMenuDefaultItem((UINT)-1,  TRUE);
+                                       menu.SetMenuDefaultItem(nFirstPos + m_nActivePage,  TRUE);
+                               }
+                               else
+#else // CE specific
+                               bActiveAsDefaultMenuItem;   // avoid level 4 warning
+#endif // _WIN32_WCE
+                               {
+                                       menu.CheckMenuRadioItem(nFirstPos, nFirstPos + nMenuItemsCount, nFirstPos + m_nActivePage, MF_BYPOSITION);
+                               }
+                       }
+               }
+               else
+               {
+                       if(bEmptyMenuItem)
+                       {
+                               menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_TABFIRST, pT->GetEmptyListText());
+                               menu.EnableMenuItem(ID_WINDOW_TABFIRST, MF_GRAYED);
+                       }
+
+                       // Remove separator if nothing else is there
+                       if(!bEmptyMenuItem && !bWindowsMenuItem && (nFirstPos > 0))
+                       {
+                               CMenuItemInfo mii;
+                               mii.fMask = MIIM_TYPE;
+                               menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii);
+                               if((mii.fType & MFT_SEPARATOR) != 0)
+                                       menu.DeleteMenu(nFirstPos - 1, MF_BYPOSITION);
+                       }
+               }
+
+               // Add "Windows..." menu item
+               if(bWindowsMenuItem)
+                       menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_SHOWTABLIST, pT->GetWindowsMenuItemText());
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CTabViewImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+               NOTIFY_HANDLER(m_nTabID, TCN_SELCHANGE, OnTabChanged)
+               NOTIFY_ID_HANDLER(m_nTabID, OnTabNotification)
+#ifndef _WIN32_WCE
+               NOTIFY_CODE_HANDLER(TTN_GETDISPINFO, OnTabGetDispInfo)
+#endif // !_WIN32_WCE
+               FORWARD_NOTIFICATIONS()
+       ALT_MSG_MAP(1)   // tab control
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, OnTabLButtonDown)
+               MESSAGE_HANDLER(WM_LBUTTONUP, OnTabLButtonUp)
+               MESSAGE_HANDLER(WM_CAPTURECHANGED, OnTabCaptureChanged)
+               MESSAGE_HANDLER(WM_MOUSEMOVE, OnTabMouseMove)
+               MESSAGE_HANDLER(WM_RBUTTONUP, OnTabRButtonUp)
+               MESSAGE_HANDLER(WM_SYSKEYDOWN, OnTabSysKeyDown)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->CreateTabControl();
+
+               return 0;
+       }
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               RemoveAllPages();
+
+               if(m_bDestroyImageList)
+               {
+                       CImageList il = m_tab.SetImageList(NULL);
+                       if(il.m_hImageList != NULL)
+                               il.Destroy();
+               }
+
+               return 0;
+       }
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(m_nActivePage != -1)
+                       ::SetFocus(GetPageHWND(m_nActivePage));
+               return 0;
+       }
+
+       LRESULT OnTabChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+       {
+               SetActivePage(m_tab.GetCurSel());
+               T* pT = static_cast<T*>(this);
+               pT->OnPageActivated(m_nActivePage);
+
+               return 0;
+       }
+
+       LRESULT OnTabNotification(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+       {
+               // nothing to do - this just blocks all tab control
+               // notifications from being propagated further
+               return 0;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnTabGetDispInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               LPNMTTDISPINFO pTTDI = (LPNMTTDISPINFO)pnmh;
+               if(pTTDI->hdr.hwndFrom == m_tab.GetTooltips())
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateTooltipText(pTTDI);
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+
+               return 0;
+       }
+#endif // !_WIN32_WCE
+
+// Tab control message handlers
+       LRESULT OnTabLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(m_tab.GetItemCount() > 1)
+               {
+                       m_bTabCapture = true;
+                       m_tab.SetCapture();
+
+                       m_ptStartDrag.x = GET_X_LPARAM(lParam);
+                       m_ptStartDrag.y = GET_Y_LPARAM(lParam);
+               }
+
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnTabLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(m_bTabCapture)
+               {
+                       if(m_bTabDrag)
+                       {
+                               TCHITTESTINFO hti = { 0 };
+                               hti.pt.x = GET_X_LPARAM(lParam);
+                               hti.pt.y = GET_Y_LPARAM(lParam);
+                               int nItem = m_tab.HitTest(&hti);
+                               if(nItem != -1)
+                                       MovePage(m_nActivePage, nItem);
+                       }
+
+                       ::ReleaseCapture();
+               }
+
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnTabCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_bTabCapture)
+               {
+                       m_bTabCapture = false;
+
+                       if(m_bTabDrag)
+                       {
+                               m_bTabDrag = false;
+                               T* pT = static_cast<T*>(this);
+                               pT->DrawMoveMark(-1);
+
+#ifndef _WIN32_WCE
+                               m_ilDrag.DragLeave(GetDesktopWindow());
+#endif // !_WIN32_WCE
+                               m_ilDrag.EndDrag();
+
+                               m_ilDrag.Destroy();
+                               m_ilDrag.m_hImageList = NULL;
+                       }
+               }
+
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnTabMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               bHandled = FALSE;
+
+               if(m_bTabCapture)
+               {
+                       POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+
+                       if(!m_bTabDrag)
+                       {
+#ifndef _WIN32_WCE
+                               if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CXDRAG) ||
+                                  abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CYDRAG))
+#else // CE specific
+                               if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= 4 ||
+                                  abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= 4)
+#endif // _WIN32_WCE
+                               {
+                                       T* pT = static_cast<T*>(this);
+                                       pT->GenerateDragImage(m_nActivePage);
+
+                                       int cxCursor = ::GetSystemMetrics(SM_CXCURSOR);
+                                       int cyCursor = ::GetSystemMetrics(SM_CYCURSOR);
+                                       m_ilDrag.BeginDrag(0, -(cxCursor / 2), -(cyCursor / 2));
+#ifndef _WIN32_WCE
+                                       POINT ptEnter = m_ptStartDrag;
+                                       m_tab.ClientToScreen(&ptEnter);
+                                       m_ilDrag.DragEnter(GetDesktopWindow(), ptEnter);
+#endif // !_WIN32_WCE
+
+                                       m_bTabDrag = true;
+                               }
+                       }
+
+                       if(m_bTabDrag)
+                       {
+                               TCHITTESTINFO hti = { 0 };
+                               hti.pt = pt;
+                               int nItem = m_tab.HitTest(&hti);
+
+                               T* pT = static_cast<T*>(this);
+                               pT->SetMoveCursor(nItem != -1);
+
+                               if(m_nInsertItem != nItem)
+                                       pT->DrawMoveMark(nItem);
+
+                               m_ilDrag.DragShowNolock((nItem != -1) ? TRUE : FALSE);
+                               m_tab.ClientToScreen(&pt);
+                               m_ilDrag.DragMove(pt);
+
+                               bHandled = TRUE;
+                       }
+               }
+
+               return 0;
+       }
+
+       LRESULT OnTabRButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               TCHITTESTINFO hti = { 0 };
+               hti.pt.x = GET_X_LPARAM(lParam);
+               hti.pt.y = GET_Y_LPARAM(lParam);
+               int nItem = m_tab.HitTest(&hti);
+               if(nItem != -1)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->OnContextMenu(nItem, hti.pt);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnTabSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               bool bShift = (::GetKeyState(VK_SHIFT) < 0);
+               if(wParam == VK_F10 && bShift)
+               {
+                       if(m_nActivePage != -1)
+                       {
+                               RECT rect = { 0 };
+                               m_tab.GetItemRect(m_nActivePage, &rect);
+                               POINT pt = { rect.left, rect.bottom };
+                               T* pT = static_cast<T*>(this);
+                               pT->OnContextMenu(m_nActivePage, pt);
+                       }
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+
+               return 0;
+       }
+
+// Implementation helpers
+       bool IsValidPageIndex(int nPage) const
+       {
+               return (nPage >= 0 && nPage < GetPageCount());
+       }
+
+       bool MovePage(int nMovePage, int nInsertBeforePage)
+       {
+               ATLASSERT(IsValidPageIndex(nMovePage));
+               ATLASSERT(IsValidPageIndex(nInsertBeforePage));
+
+               if(!IsValidPageIndex(nMovePage) || !IsValidPageIndex(nInsertBeforePage))
+                       return false;
+
+               if(nMovePage == nInsertBeforePage)
+                       return true;   // nothing to do
+
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
+               if(lpstrTabText == NULL)
+                       return false;
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
+               tcix.tciheader.pszText = lpstrTabText;
+               tcix.tciheader.cchTextMax = m_cchTabTextLength + 1;
+               BOOL bRet = m_tab.GetItem(nMovePage, tcix);
+               ATLASSERT(bRet != FALSE);
+               if(bRet == FALSE)
+                       return false;
+
+               int nInsertItem = (nInsertBeforePage > nMovePage) ? nInsertBeforePage + 1 : nInsertBeforePage;
+               int nNewItem = m_tab.InsertItem(nInsertItem, tcix);
+               ATLASSERT(nNewItem == nInsertItem);
+               if(nNewItem != nInsertItem)
+               {
+                       ATLVERIFY(m_tab.DeleteItem(nNewItem));
+                       return false;
+               }
+
+               if(nMovePage > nInsertBeforePage)
+                       ATLVERIFY(m_tab.DeleteItem(nMovePage + 1) != FALSE);
+               else if(nMovePage < nInsertBeforePage)
+                       ATLVERIFY(m_tab.DeleteItem(nMovePage) != FALSE);
+
+               SetActivePage(nInsertBeforePage);
+               T* pT = static_cast<T*>(this);
+               pT->OnPageActivated(m_nActivePage);
+
+               return true;
+       }
+
+// Implementation overrideables
+       bool CreateTabControl()
+       {
+#ifndef _WIN32_WCE
+               m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_TOOLTIPS, 0, m_nTabID);
+#else // CE specific
+               m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, m_nTabID);
+#endif // _WIN32_WCE
+               ATLASSERT(m_tab.m_hWnd != NULL);
+               if(m_tab.m_hWnd == NULL)
+                       return false;
+
+               m_tab.SetFont(AtlGetDefaultGuiFont());
+
+               m_tab.SetItemExtra(sizeof(TABVIEWPAGE));
+
+               T* pT = static_cast<T*>(this);
+               m_cyTabHeight = pT->CalcTabHeight();
+
+               return true;
+       }
+
+       int CalcTabHeight()
+       {
+               int nCount = m_tab.GetItemCount();
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_TEXT;
+               tcix.tciheader.pszText = _T("NS");
+               int nIndex = m_tab.InsertItem(nCount, tcix);
+
+               RECT rect = { 0, 0, 1000, 1000 };
+               m_tab.AdjustRect(FALSE, &rect);
+
+               RECT rcWnd = { 0, 0, 1000, rect.top };
+               ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle());
+
+               int nHeight = rcWnd.bottom - rcWnd.top;
+
+               m_tab.DeleteItem(nIndex);
+
+               return nHeight;
+       }
+
+       void ShowTabControl(bool bShow)
+       {
+               m_tab.ShowWindow(bShow ? SW_SHOWNOACTIVATE : SW_HIDE);
+       }
+
+       void UpdateLayout()
+       {
+               RECT rect;
+               GetClientRect(&rect);
+
+               if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0))
+                       m_tab.SetWindowPos(NULL, 0, 0, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER);
+
+               if(m_nActivePage != -1)
+                       ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, m_cyTabHeight, rect.right - rect.left, rect.bottom - rect.top - m_cyTabHeight, SWP_NOZORDER);
+       }
+
+       void UpdateMenu()
+       {
+               if(m_menu.m_hMenu != NULL)
+                       BuildWindowMenu(m_menu, m_nMenuItemsCount, m_bEmptyMenuItem, m_bWindowsMenuItem, m_bActivePageMenuItem, m_bActiveAsDefaultMenuItem);
+       }
+
+       void UpdateTitleBar()
+       {
+               if(!m_wndTitleBar.IsWindow() || m_lpstrTitleBarBase == NULL)
+                       return;   // nothing to do
+
+               if(m_nActivePage != -1)
+               {
+                       T* pT = static_cast<T*>(this);
+                       LPCTSTR lpstrTitle = pT->GetPageTitle(m_nActivePage);
+                       LPCTSTR lpstrDivider = pT->GetTitleDividerText();
+                       int cchBuffer = m_cchTitleBarLength + lstrlen(lpstrDivider) + lstrlen(m_lpstrTitleBarBase) + 1;
+                       CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+                       LPTSTR lpstrPageTitle = buff.Allocate(cchBuffer);
+                       ATLASSERT(lpstrPageTitle != NULL);
+                       if(lpstrPageTitle != NULL)
+                       {
+                               pT->ShortenTitle(lpstrTitle, lpstrPageTitle, m_cchTitleBarLength + 1);
+                               SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, lpstrDivider);
+                               SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, m_lpstrTitleBarBase);
+                       }
+                       else
+                       {
+                               lpstrPageTitle = m_lpstrTitleBarBase;
+                       }
+
+                       m_wndTitleBar.SetWindowText(lpstrPageTitle);
+               }
+               else
+               {
+                       m_wndTitleBar.SetWindowText(m_lpstrTitleBarBase);
+               }
+       }
+
+       void DrawMoveMark(int nItem)
+       {
+               T* pT = static_cast<T*>(this);
+
+               if(m_nInsertItem != -1)
+               {
+                       RECT rect = { 0 };
+                       pT->GetMoveMarkRect(rect);
+                       m_tab.InvalidateRect(&rect);
+               }
+
+               m_nInsertItem = nItem;
+
+               if(m_nInsertItem != -1)
+               {
+                       CClientDC dc(m_tab.m_hWnd);
+
+                       RECT rect = { 0 };
+                       pT->GetMoveMarkRect(rect);
+
+                       CPen pen;
+                       pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWTEXT));
+                       CBrush brush;
+                       brush.CreateSolidBrush(::GetSysColor(COLOR_WINDOWTEXT));
+
+                       HPEN hPenOld = dc.SelectPen(pen);
+                       HBRUSH hBrushOld = dc.SelectBrush(brush);
+
+                       int x = rect.left;
+                       int y = rect.top;
+                       POINT ptsTop[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y + m_cyMoveMark } };
+                       dc.Polygon(ptsTop, 3);
+
+                       y = rect.bottom - 1;
+                       POINT ptsBottom[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y - m_cyMoveMark } };
+                       dc.Polygon(ptsBottom, 3);
+
+                       dc.SelectPen(hPenOld);
+                       dc.SelectBrush(hBrushOld);
+               }
+       }
+
+       void GetMoveMarkRect(RECT& rect) const
+       {
+               m_tab.GetClientRect(&rect);
+
+               RECT rcItem = { 0 };
+               m_tab.GetItemRect(m_nInsertItem, &rcItem);
+
+               if(m_nInsertItem <= m_nActivePage)
+               {
+                       rect.left = rcItem.left - m_cxMoveMark / 2 - 1;
+                       rect.right = rcItem.left + m_cxMoveMark / 2;
+               }
+               else
+               {
+                       rect.left = rcItem.right - m_cxMoveMark / 2 - 1;
+                       rect.right = rcItem.right + m_cxMoveMark / 2;
+               }
+       }
+
+       void SetMoveCursor(bool bCanMove)
+       {
+               ::SetCursor(::LoadCursor(NULL, bCanMove ? IDC_ARROW : IDC_NO));
+       }
+
+       void GenerateDragImage(int nItem)
+       {
+               ATLASSERT(IsValidPageIndex(nItem));
+
+#ifndef _WIN32_WCE
+               RECT rcItem = { 0 };
+               m_tab.GetItemRect(nItem, &rcItem);
+               ::InflateRect(&rcItem, 2, 2);   // make bigger to cover selected item
+#else // CE specific
+               nItem;   // avoid level 4 warning
+               RECT rcItem = { 0, 0, 40, 20 };
+#endif // _WIN32_WCE
+
+               ATLASSERT(m_ilDrag.m_hImageList == NULL);
+               m_ilDrag.Create(rcItem.right - rcItem.left, rcItem.bottom - rcItem.top, ILC_COLORDDB | ILC_MASK, 1, 1);
+
+               CClientDC dc(m_hWnd);
+               CDC dcMem;
+               dcMem.CreateCompatibleDC(dc);
+               ATLASSERT(dcMem.m_hDC != NULL);
+               dcMem.SetViewportOrg(-rcItem.left, -rcItem.top);
+
+               CBitmap bmp;
+               bmp.CreateCompatibleBitmap(dc, rcItem.right - rcItem.left, rcItem.bottom - rcItem.top);
+               ATLASSERT(bmp.m_hBitmap != NULL);
+
+               HBITMAP hBmpOld = dcMem.SelectBitmap(bmp);
+#ifndef _WIN32_WCE
+               m_tab.SendMessage(WM_PRINTCLIENT, (WPARAM)dcMem.m_hDC);
+#else // CE specific
+               dcMem.Rectangle(&rcItem);
+#endif // _WIN32_WCE
+               dcMem.SelectBitmap(hBmpOld);
+
+               ATLVERIFY(m_ilDrag.Add(bmp.m_hBitmap, RGB(255, 0, 255)) != -1);
+       }
+
+       void ShortenTitle(LPCTSTR lpstrTitle, LPTSTR lpstrShortTitle, int cchShortTitle)
+       {
+               if(lstrlen(lpstrTitle) >= cchShortTitle)
+               {
+                       LPCTSTR lpstrEllipsis = _T("...");
+                       int cchEllipsis = lstrlen(lpstrEllipsis);
+                       SecureHelper::strncpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle, cchShortTitle - cchEllipsis - 1);
+                       SecureHelper::strcat_x(lpstrShortTitle, cchShortTitle, lpstrEllipsis);
+               }
+               else
+               {
+                       SecureHelper::strcpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle);
+               }
+       }
+
+#ifndef _WIN32_WCE
+       void UpdateTooltipText(LPNMTTDISPINFO pTTDI)
+       {
+               ATLASSERT(pTTDI != NULL);
+               pTTDI->lpszText = (LPTSTR)GetPageTitle((int)pTTDI->hdr.idFrom);
+       }
+#endif // !_WIN32_WCE
+
+// Text for menu items and title bar - override to provide different strings
+       static LPCTSTR GetEmptyListText()
+       {
+               return _T("(Empty)");
+       }
+
+       static LPCTSTR GetWindowsMenuItemText()
+       {
+               return _T("&Windows...");
+       }
+
+       static LPCTSTR GetTitleDividerText()
+       {
+               return _T(" - ");
+       }
+
+// Notifications - override to provide different behavior
+       void OnPageActivated(int nPage)
+       {
+               NMHDR nmhdr = { 0 };
+               nmhdr.hwndFrom = m_hWnd;
+               nmhdr.idFrom = nPage;
+               nmhdr.code = TBVN_PAGEACTIVATED;
+               ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr);
+       }
+
+       void OnContextMenu(int nPage, POINT pt)
+       {
+               m_tab.ClientToScreen(&pt);
+
+               TBVCONTEXTMENUINFO cmi = { 0 };
+               cmi.hdr.hwndFrom = m_hWnd;
+               cmi.hdr.idFrom = nPage;
+               cmi.hdr.code = TBVN_CONTEXTMENU;
+               cmi.pt = pt;
+               ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&cmi);
+       }
+};
+
+
+class CTabView : public CTabViewImpl<CTabView>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("WTL_TabView"), 0, COLOR_APPWORKSPACE)
+};
+
+}; // namespace WTL
+
+#endif // __ATLCTRLX_H__
diff --git a/include/WTL/Include/atlddx.h b/include/WTL/Include/atlddx.h
new file mode 100644 (file)
index 0000000..31456a4
--- /dev/null
@@ -0,0 +1,624 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLDDX_H__
+#define __ATLDDX_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlddx.h requires atlapp.h to be included first
+#endif
+
+#if defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT)
+       #error Cannot use floating point DDX with _ATL_MIN_CRT defined
+#endif // defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT)
+
+#ifdef _ATL_USE_DDX_FLOAT
+  #include <float.h>
+#endif // _ATL_USE_DDX_FLOAT
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CWinDataExchange<T>
+
+
+namespace WTL
+{
+
+// Constants
+#define DDX_LOAD       FALSE
+#define DDX_SAVE       TRUE
+
+// DDX map macros
+#define BEGIN_DDX_MAP(thisClass) \
+       BOOL DoDataExchange(BOOL bSaveAndValidate = FALSE, UINT nCtlID = (UINT)-1) \
+       { \
+               bSaveAndValidate; \
+               nCtlID;
+
+#define DDX_TEXT(nID, var) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate)) \
+                               return FALSE; \
+               }
+
+#define DDX_TEXT_LEN(nID, var, len) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate, TRUE, len)) \
+                               return FALSE; \
+               }
+
+#define DDX_INT(nID, var) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Int(nID, var, TRUE, bSaveAndValidate)) \
+                               return FALSE; \
+               }
+
+#define DDX_INT_RANGE(nID, var, min, max) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Int(nID, var, TRUE, bSaveAndValidate, TRUE, min, max)) \
+                               return FALSE; \
+               }
+
+#define DDX_UINT(nID, var) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Int(nID, var, FALSE, bSaveAndValidate)) \
+                               return FALSE; \
+               }
+
+#define DDX_UINT_RANGE(nID, var, min, max) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Int(nID, var, FALSE, bSaveAndValidate, TRUE, min, max)) \
+                               return FALSE; \
+               }
+
+#ifdef _ATL_USE_DDX_FLOAT
+#define DDX_FLOAT(nID, var) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Float(nID, var, bSaveAndValidate)) \
+                               return FALSE; \
+               }
+
+#define DDX_FLOAT_RANGE(nID, var, min, max) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max)) \
+                               return FALSE; \
+               }
+#define DDX_FLOAT_P(nID, var, precision) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Float(nID, var, bSaveAndValidate, FALSE, 0, 0, precision)) \
+                               return FALSE; \
+               }
+
+#define DDX_FLOAT_P_RANGE(nID, var, min, max, precision) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+               { \
+                       if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max, precision)) \
+                               return FALSE; \
+               }
+#endif // _ATL_USE_DDX_FLOAT
+
+#define DDX_CONTROL(nID, obj) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+                       DDX_Control(nID, obj, bSaveAndValidate);
+
+#define DDX_CONTROL_HANDLE(nID, obj) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+                       DDX_Control_Handle(nID, obj, bSaveAndValidate);
+
+#define DDX_CHECK(nID, var) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+                       DDX_Check(nID, var, bSaveAndValidate);
+
+#define DDX_RADIO(nID, var) \
+               if(nCtlID == (UINT)-1 || nCtlID == nID) \
+                       DDX_Radio(nID, var, bSaveAndValidate);
+
+#define END_DDX_MAP() \
+               return TRUE; \
+       }
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CWinDataExchange - provides support for DDX
+
+template <class T>
+class CWinDataExchange
+{
+public:
+// Data exchange method - override in your derived class
+       BOOL DoDataExchange(BOOL /*bSaveAndValidate*/ = FALSE, UINT /*nCtlID*/ = (UINT)-1)
+       {
+               // this one should never be called, override it in
+               // your derived class by implementing DDX map
+               ATLASSERT(FALSE);
+               return FALSE;
+       }
+
+// Helpers for validation error reporting
+       enum _XDataType
+       {
+               ddxDataNull = 0,
+               ddxDataText = 1,
+               ddxDataInt = 2,
+               ddxDataFloat = 3,
+               ddxDataDouble = 4
+       };
+
+       struct _XTextData
+       {
+               int nLength;
+               int nMaxLength;
+       };
+
+       struct _XIntData
+       {
+               long nVal;
+               long nMin;
+               long nMax;
+       };
+
+       struct _XFloatData
+       {
+               double nVal;
+               double nMin;
+               double nMax;
+       };
+
+       struct _XData
+       {
+               _XDataType nDataType;
+               union
+               {
+                       _XTextData textData;
+                       _XIntData intData;
+                       _XFloatData floatData;
+               };
+       };
+
+// Text exchange
+       BOOL DDX_Text(UINT nID, LPTSTR lpstrText, int cbSize, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0)
+       {
+               T* pT = static_cast<T*>(this);
+               BOOL bSuccess = TRUE;
+
+               if(bSave)
+               {
+                       HWND hWndCtrl = pT->GetDlgItem(nID);
+                       int nRetLen = ::GetWindowText(hWndCtrl, lpstrText, cbSize / sizeof(TCHAR));
+                       if(nRetLen < ::GetWindowTextLength(hWndCtrl))
+                               bSuccess = FALSE;
+               }
+               else
+               {
+                       ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength);
+                       bSuccess = pT->SetDlgItemText(nID, lpstrText);
+               }
+
+               if(!bSuccess)
+               {
+                       pT->OnDataExchangeError(nID, bSave);
+               }
+               else if(bSave && bValidate)   // validation
+               {
+                       ATLASSERT(nLength > 0);
+                       if(lstrlen(lpstrText) > nLength)
+                       {
+                               _XData data = { ddxDataText };
+                               data.textData.nLength = lstrlen(lpstrText);
+                               data.textData.nMaxLength = nLength;
+                               pT->OnDataValidateError(nID, bSave, data);
+                               bSuccess = FALSE;
+                       }
+               }
+               return bSuccess;
+       }
+
+       BOOL DDX_Text(UINT nID, BSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0)
+       {
+               T* pT = static_cast<T*>(this);
+               BOOL bSuccess = TRUE;
+
+               if(bSave)
+               {
+                       bSuccess = pT->GetDlgItemText(nID, bstrText);
+               }
+               else
+               {
+                       USES_CONVERSION;
+                       LPTSTR lpstrText = OLE2T(bstrText);
+                       ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength);
+                       bSuccess = pT->SetDlgItemText(nID, lpstrText);
+               }
+
+               if(!bSuccess)
+               {
+                       pT->OnDataExchangeError(nID, bSave);
+               }
+               else if(bSave && bValidate)   // validation
+               {
+                       ATLASSERT(nLength > 0);
+                       if((int)::SysStringLen(bstrText) > nLength)
+                       {
+                               _XData data = { ddxDataText };
+                               data.textData.nLength = (int)::SysStringLen(bstrText);
+                               data.textData.nMaxLength = nLength;
+                               pT->OnDataValidateError(nID, bSave, data);
+                               bSuccess = FALSE;
+                       }
+               }
+               return bSuccess;
+       }
+
+       BOOL DDX_Text(UINT nID, ATL::CComBSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0)
+       {
+               T* pT = static_cast<T*>(this);
+               BOOL bSuccess = TRUE;
+
+               if(bSave)
+               {
+                       bSuccess = pT->GetDlgItemText(nID, (BSTR&)bstrText);
+               }
+               else
+               {
+                       USES_CONVERSION;
+                       LPTSTR lpstrText = OLE2T(bstrText);
+                       ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength);
+                       bSuccess = pT->SetDlgItemText(nID, lpstrText);
+               }
+
+               if(!bSuccess)
+               {
+                       pT->OnDataExchangeError(nID, bSave);
+               }
+               else if(bSave && bValidate)   // validation
+               {
+                       ATLASSERT(nLength > 0);
+                       if((int)bstrText.Length() > nLength)
+                       {
+                               _XData data = { ddxDataText };
+                               data.textData.nLength = (int)bstrText.Length();
+                               data.textData.nMaxLength = nLength;
+                               pT->OnDataValidateError(nID, bSave, data);
+                               bSuccess = FALSE;
+                       }
+               }
+               return bSuccess;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       BOOL DDX_Text(UINT nID, _CSTRING_NS::CString& strText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0)
+       {
+               T* pT = static_cast<T*>(this);
+               BOOL bSuccess = TRUE;
+
+               if(bSave)
+               {
+                       HWND hWndCtrl = pT->GetDlgItem(nID);
+                       int nLen = ::GetWindowTextLength(hWndCtrl);
+                       int nRetLen = -1;
+                       LPTSTR lpstr = strText.GetBufferSetLength(nLen);
+                       if(lpstr != NULL)
+                       {
+                               nRetLen = ::GetWindowText(hWndCtrl, lpstr, nLen + 1);
+                               strText.ReleaseBuffer();
+                       }
+                       if(nRetLen < nLen)
+                               bSuccess = FALSE;
+               }
+               else
+               {
+                       bSuccess = pT->SetDlgItemText(nID, strText);
+               }
+
+               if(!bSuccess)
+               {
+                       pT->OnDataExchangeError(nID, bSave);
+               }
+               else if(bSave && bValidate)   // validation
+               {
+                       ATLASSERT(nLength > 0);
+                       if(strText.GetLength() > nLength)
+                       {
+                               _XData data = { ddxDataText };
+                               data.textData.nLength = strText.GetLength();
+                               data.textData.nMaxLength = nLength;
+                               pT->OnDataValidateError(nID, bSave, data);
+                               bSuccess = FALSE;
+                       }
+               }
+               return bSuccess;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+// Numeric exchange
+       template <class Type>
+       BOOL DDX_Int(UINT nID, Type& nVal, BOOL bSigned, BOOL bSave, BOOL bValidate = FALSE, Type nMin = 0, Type nMax = 0)
+       {
+               T* pT = static_cast<T*>(this);
+               BOOL bSuccess = TRUE;
+
+               if(bSave)
+               {
+                       nVal = (Type)pT->GetDlgItemInt(nID, &bSuccess, bSigned);
+               }
+               else
+               {
+                       ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax);
+                       bSuccess = pT->SetDlgItemInt(nID, nVal, bSigned);
+               }
+
+               if(!bSuccess)
+               {
+                       pT->OnDataExchangeError(nID, bSave);
+               }
+               else if(bSave && bValidate)   // validation
+               {
+                       ATLASSERT(nMin != nMax);
+                       if(nVal < nMin || nVal > nMax)
+                       {
+                               _XData data = { ddxDataInt };
+                               data.intData.nVal = (long)nVal;
+                               data.intData.nMin = (long)nMin;
+                               data.intData.nMax = (long)nMax;
+                               pT->OnDataValidateError(nID, bSave, data);
+                               bSuccess = FALSE;
+                       }
+               }
+               return bSuccess;
+       }
+
+// Float exchange
+#ifdef _ATL_USE_DDX_FLOAT
+       static BOOL _AtlSimpleFloatParse(LPCTSTR lpszText, double& d)
+       {
+               ATLASSERT(lpszText != NULL);
+               while (*lpszText == _T(' ') || *lpszText == _T('\t'))
+                       lpszText++;
+
+               TCHAR chFirst = lpszText[0];
+               d = _tcstod(lpszText, (LPTSTR*)&lpszText);
+               if (d == 0.0 && chFirst != _T('0'))
+                       return FALSE;   // could not convert
+               while (*lpszText == _T(' ') || *lpszText == _T('\t'))
+                       lpszText++;
+
+               if (*lpszText != _T('\0'))
+                       return FALSE;   // not terminated properly
+
+               return TRUE;
+       }
+
+       BOOL DDX_Float(UINT nID, float& nVal, BOOL bSave, BOOL bValidate = FALSE, float nMin = 0.F, float nMax = 0.F, int nPrecision = FLT_DIG)
+       {
+               T* pT = static_cast<T*>(this);
+               BOOL bSuccess = TRUE;
+               const int cchBuff = 32;
+               TCHAR szBuff[cchBuff] = { 0 };
+
+               if(bSave)
+               {
+                       pT->GetDlgItemText(nID, szBuff, cchBuff);
+                       double d = 0;
+                       if(_AtlSimpleFloatParse(szBuff, d))
+                               nVal = (float)d;
+                       else
+                               bSuccess = FALSE;
+               }
+               else
+               {
+                       ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax);
+                       SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal);
+                       bSuccess = pT->SetDlgItemText(nID, szBuff);
+               }
+
+               if(!bSuccess)
+               {
+                       pT->OnDataExchangeError(nID, bSave);
+               }
+               else if(bSave && bValidate)   // validation
+               {
+                       ATLASSERT(nMin != nMax);
+                       if(nVal < nMin || nVal > nMax)
+                       {
+                               _XData data = { ddxDataFloat };
+                               data.floatData.nVal = (double)nVal;
+                               data.floatData.nMin = (double)nMin;
+                               data.floatData.nMax = (double)nMax;
+                               pT->OnDataValidateError(nID, bSave, data);
+                               bSuccess = FALSE;
+                       }
+               }
+               return bSuccess;
+       }
+
+       BOOL DDX_Float(UINT nID, double& nVal, BOOL bSave, BOOL bValidate = FALSE, double nMin = 0., double nMax = 0., int nPrecision = DBL_DIG)
+       {
+               T* pT = static_cast<T*>(this);
+               BOOL bSuccess = TRUE;
+               const int cchBuff = 32;
+               TCHAR szBuff[cchBuff] = { 0 };
+
+               if(bSave)
+               {
+                       pT->GetDlgItemText(nID, szBuff, cchBuff);
+                       double d = 0;
+                       if(_AtlSimpleFloatParse(szBuff, d))
+                               nVal = d;
+                       else
+                               bSuccess = FALSE;
+               }
+               else
+               {
+                       ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax);
+                       SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal);
+                       bSuccess = pT->SetDlgItemText(nID, szBuff);
+               }
+
+               if(!bSuccess)
+               {
+                       pT->OnDataExchangeError(nID, bSave);
+               }
+               else if(bSave && bValidate)   // validation
+               {
+                       ATLASSERT(nMin != nMax);
+                       if(nVal < nMin || nVal > nMax)
+                       {
+                               _XData data = { ddxDataFloat };
+                               data.floatData.nVal = nVal;
+                               data.floatData.nMin = nMin;
+                               data.floatData.nMax = nMax;
+                               pT->OnDataValidateError(nID, bSave, data);
+                               bSuccess = FALSE;
+                       }
+               }
+               return bSuccess;
+       }
+#endif // _ATL_USE_DDX_FLOAT
+
+// Full control subclassing (for CWindowImpl derived controls)
+       template <class TControl>
+       void DDX_Control(UINT nID, TControl& ctrl, BOOL bSave)
+       {
+               if(!bSave && ctrl.m_hWnd == NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       ctrl.SubclassWindow(pT->GetDlgItem(nID));
+               }
+       }
+
+// Simple control attaching (for HWND wrapper controls)
+       template <class TControl>
+       void DDX_Control_Handle(UINT nID, TControl& ctrl, BOOL bSave)
+       {
+               if(!bSave && ctrl.m_hWnd == NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       ctrl = pT->GetDlgItem(nID);
+               }
+       }
+
+// Control state
+       void DDX_Check(UINT nID, int& nValue, BOOL bSave)
+       {
+               T* pT = static_cast<T*>(this);
+               HWND hWndCtrl = pT->GetDlgItem(nID);
+               if(bSave)
+               {
+                       nValue = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L);
+                       ATLASSERT(nValue >= 0 && nValue <= 2);
+               }
+               else
+               {
+                       if(nValue < 0 || nValue > 2)
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - dialog data checkbox value (%d) out of range.\n"), nValue);
+                               nValue = 0;  // default to off
+                       }
+                       ::SendMessage(hWndCtrl, BM_SETCHECK, nValue, 0L);
+               }
+       }
+
+       // variant that supports bool (checked/not-checked, no intermediate state)
+       void DDX_Check(UINT nID, bool& bCheck, BOOL bSave)
+       {
+               int nValue = bCheck ? 1 : 0;
+               DDX_Check(nID, nValue, bSave);
+
+               if(bSave)
+               {
+                       if(nValue == 2)
+                               ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - checkbox state (%d) out of supported range.\n"), nValue);
+                       bCheck = (nValue == 1);
+               }
+       }
+
+       void DDX_Radio(UINT nID, int& nValue, BOOL bSave)
+       {
+               T* pT = static_cast<T*>(this);
+               HWND hWndCtrl = pT->GetDlgItem(nID);
+               ATLASSERT(hWndCtrl != NULL);
+
+               // must be first in a group of auto radio buttons
+               ATLASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP);
+               ATLASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON);
+
+               if(bSave)
+                       nValue = -1;     // value if none found
+
+               // walk all children in group
+               int nButton = 0;
+               do
+               {
+                       if(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON)
+                       {
+                               // control in group is a radio button
+                               if(bSave)
+                               {
+                                       if(::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L) != 0)
+                                       {
+                                               ATLASSERT(nValue == -1);    // only set once
+                                               nValue = nButton;
+                                       }
+                               }
+                               else
+                               {
+                                       // select button
+                                       ::SendMessage(hWndCtrl, BM_SETCHECK, (nButton == nValue), 0L);
+                               }
+                               nButton++;
+                       }
+                       else
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - skipping non-radio button in group.\n"));
+                       }
+                       hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT);
+               }
+               while (hWndCtrl != NULL && !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP));
+       }
+
+// Overrideables
+       void OnDataExchangeError(UINT nCtrlID, BOOL /*bSave*/)
+       {
+               // Override to display an error message
+               ::MessageBeep((UINT)-1);
+               T* pT = static_cast<T*>(this);
+               ::SetFocus(pT->GetDlgItem(nCtrlID));
+       }
+
+       void OnDataValidateError(UINT nCtrlID, BOOL /*bSave*/, _XData& /*data*/)
+       {
+               // Override to display an error message
+               ::MessageBeep((UINT)-1);
+               T* pT = static_cast<T*>(this);
+               ::SetFocus(pT->GetDlgItem(nCtrlID));
+       }
+};
+
+}; // namespace WTL
+
+#endif // __ATLDDX_H__
diff --git a/include/WTL/Include/atldlgs.h b/include/WTL/Include/atldlgs.h
new file mode 100644 (file)
index 0000000..feb7251
--- /dev/null
@@ -0,0 +1,6407 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLDLGS_H__
+#define __ATLDLGS_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atldlgs.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atldlgs.h requires atlwin.h to be included first
+#endif
+
+#include <commdlg.h>
+#include <shlobj.h>
+
+#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
+  #include <shobjidl.h>
+#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CFileDialogImpl<T>
+// CFileDialog
+// CFileDialogEx
+// CMultiFileDialogImpl<T>
+// CMultiFileDialog
+// CShellFileDialogImpl<T>
+// CShellFileOpenDialogImpl<T>
+// CShellFileOpenDialog
+// CShellFileSaveDialogImpl<T>
+// CShellFileSaveDialog
+// CFolderDialogImpl<T>
+// CFolderDialog
+// CFontDialogImpl<T>
+// CFontDialog
+// CRichEditFontDialogImpl<T>
+// CRichEditFontDialog
+// CColorDialogImpl<T>
+// CColorDialog
+// CPrintDialogImpl<T>
+// CPrintDialog
+// CPrintDialogExImpl<T>
+// CPrintDialogEx
+// CPageSetupDialogImpl<T>
+// CPageSetupDialog
+// CFindReplaceDialogImpl<T>
+// CFindReplaceDialog
+//
+// CDialogBaseUnits
+// CMemDlgTemplate
+// CIndirectDialogImpl<T, TDlgTemplate, TBase>
+//
+// CPropertySheetWindow
+// CPropertySheetImpl<T, TBase>
+// CPropertySheet
+// CPropertyPageWindow
+// CPropertyPageImpl<T, TBase>
+// CPropertyPage<t_wDlgTemplateID>
+// CAxPropertyPageImpl<T, TBase>
+// CAxPropertyPage<t_wDlgTemplateID>
+//
+// CWizard97SheetWindow
+// CWizard97SheetImpl<T, TBase>
+// CWizard97Sheet
+// CWizard97PageWindow
+// CWizard97PageImpl<T, TBase>
+// CWizard97ExteriorPageImpl<T, TBase>
+// CWizard97InteriorPageImpl<T, TBase>
+//
+// CAeroWizardFrameWindow
+// CAeroWizardFrameImpl<T, TBase>
+// CAeroWizardFrame
+// CAeroWizardPageWindow
+// CAeroWizardPageImpl<T, TBase>
+// CAeroWizardPage<t_wDlgTemplateID>
+// CAeroWizardAxPageImpl<T, TBase>
+// CAeroWizardAxPage<t_wDlgTemplateID>
+//
+// CTaskDialogConfig
+// CTaskDialogImpl<T>
+// CTaskDialog
+//
+// Global functions:
+//   AtlTaskDialog()
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CFileDialogImpl - used for File Open or File Save As
+
+// compatibility with the old (vc6.0) headers
+#if (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
+  #ifndef CDSIZEOF_STRUCT
+    #define CDSIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
+  #endif
+  #define OPENFILENAME_SIZE_VERSION_400A  CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
+  #define OPENFILENAME_SIZE_VERSION_400W  CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
+  #ifdef UNICODE
+    #define OPENFILENAME_SIZE_VERSION_400  OPENFILENAME_SIZE_VERSION_400W
+  #else
+    #define OPENFILENAME_SIZE_VERSION_400  OPENFILENAME_SIZE_VERSION_400A
+  #endif // !UNICODE
+#endif // (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
+
+#if !defined(_WIN32_WCE) && !defined(CDN_INCLUDEITEM)
+  #define CDN_INCLUDEITEM         (CDN_FIRST - 0x0007)
+#endif
+
+template <class T>
+class ATL_NO_VTABLE CFileDialogImpl : public ATL::CDialogImplBase
+{
+public:
+#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
+       OPENFILENAMEEX m_ofn;
+#else
+       OPENFILENAME m_ofn;
+#endif
+       BOOL m_bOpenFileDialog;            // TRUE for file open, FALSE for file save
+       TCHAR m_szFileTitle[_MAX_FNAME];   // contains file title after return
+       TCHAR m_szFileName[_MAX_PATH];     // contains full path name after return
+
+       CFileDialogImpl(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
+                       LPCTSTR lpszDefExt = NULL,
+                       LPCTSTR lpszFileName = NULL,
+                       DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
+                       LPCTSTR lpszFilter = NULL,
+                       HWND hWndParent = NULL)
+       {
+               memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL
+               m_szFileName[0] = _T('\0');
+               m_szFileTitle[0] = _T('\0');
+
+               m_bOpenFileDialog = bOpenFileDialog;
+
+#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
+               m_ofn.lStructSize = bOpenFileDialog ? sizeof(m_ofn) : sizeof(OPENFILENAME);
+#else
+               m_ofn.lStructSize = sizeof(m_ofn);
+#endif
+
+#if (_WIN32_WINNT >= 0x0500)
+               // adjust struct size if running on older version of Windows
+               if(AtlIsOldWindows())
+               {
+                       ATLASSERT(sizeof(m_ofn) > OPENFILENAME_SIZE_VERSION_400);   // must be
+                       m_ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+               }
+#endif // (_WIN32_WINNT >= 0x0500)
+               m_ofn.lpstrFile = m_szFileName;
+               m_ofn.nMaxFile = _MAX_PATH;
+               m_ofn.lpstrDefExt = lpszDefExt;
+               m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
+               m_ofn.nMaxFileTitle = _MAX_FNAME;
+#ifndef _WIN32_WCE
+               m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING;
+#else // CE specific
+               m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK;
+#endif // !_WIN32_WCE
+               m_ofn.lpstrFilter = lpszFilter;
+               m_ofn.hInstance = ModuleHelper::GetResourceInstance();
+               m_ofn.lpfnHook = (LPOFNHOOKPROC)T::StartDialogProc;
+               m_ofn.hwndOwner = hWndParent;
+
+               // setup initial file name
+               if(lpszFileName != NULL)
+               SecureHelper::strncpy_x(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE);
+       }
+
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               ATLASSERT((m_ofn.Flags & OFN_ENABLEHOOK) != 0);
+               ATLASSERT(m_ofn.lpfnHook != NULL);   // can still be a user hook
+
+               ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
+
+               if(m_ofn.hwndOwner == NULL)   // set only if not specified before
+                       m_ofn.hwndOwner = hWndParent;
+
+               ATLASSERT(m_hWnd == NULL);
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBase*)this);
+
+               BOOL bRet;
+               if(m_bOpenFileDialog)
+#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
+                       bRet = ::GetOpenFileNameEx(&m_ofn);
+               else
+                       bRet = ::GetSaveFileName((LPOPENFILENAME)&m_ofn);
+#else
+                       bRet = ::GetOpenFileName(&m_ofn);
+               else
+                       bRet = ::GetSaveFileName(&m_ofn);
+#endif
+
+               m_hWnd = NULL;
+
+               return bRet ? IDOK : IDCANCEL;
+       }
+
+// Attributes
+       ATL::CWindow GetFileDialogWindow() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ATL::CWindow(GetParent());
+       }
+
+       int GetFilePath(LPTSTR lpstrFilePath, int nLength) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
+
+               return (int)GetFileDialogWindow().SendMessage(CDM_GETFILEPATH, nLength, (LPARAM)lpstrFilePath);
+       }
+
+       int GetFolderIDList(LPVOID lpBuff, int nLength) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
+
+               return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERIDLIST, nLength, (LPARAM)lpBuff);
+       }
+
+       int GetFolderPath(LPTSTR lpstrFolderPath, int nLength) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
+
+               return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERPATH, nLength, (LPARAM)lpstrFolderPath);
+       }
+
+       int GetSpec(LPTSTR lpstrSpec, int nLength) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
+
+               return (int)GetFileDialogWindow().SendMessage(CDM_GETSPEC, nLength, (LPARAM)lpstrSpec);
+       }
+
+       void SetControlText(int nCtrlID, LPCTSTR lpstrText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
+
+               GetFileDialogWindow().SendMessage(CDM_SETCONTROLTEXT, nCtrlID, (LPARAM)lpstrText);
+       }
+
+       void SetDefExt(LPCTSTR lpstrExt)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
+
+               GetFileDialogWindow().SendMessage(CDM_SETDEFEXT, 0, (LPARAM)lpstrExt);
+       }
+
+       BOOL GetReadOnlyPref() const    // return TRUE if readonly checked
+       {
+               return ((m_ofn.Flags & OFN_READONLY) != 0) ? TRUE : FALSE;
+       }
+
+// Operations
+       void HideControl(int nCtrlID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
+
+               GetFileDialogWindow().SendMessage(CDM_HIDECONTROL, nCtrlID);
+       }
+
+// Special override for common dialogs
+       BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               GetFileDialogWindow().SendMessage(WM_COMMAND, MAKEWPARAM(IDCANCEL, 0));
+               return TRUE;
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CFileDialogImpl)
+               NOTIFY_CODE_HANDLER(CDN_FILEOK, _OnFileOK)
+               NOTIFY_CODE_HANDLER(CDN_FOLDERCHANGE, _OnFolderChange)
+               NOTIFY_CODE_HANDLER(CDN_HELP, _OnHelp)
+               NOTIFY_CODE_HANDLER(CDN_INITDONE, _OnInitDone)
+               NOTIFY_CODE_HANDLER(CDN_SELCHANGE, _OnSelChange)
+               NOTIFY_CODE_HANDLER(CDN_SHAREVIOLATION, _OnShareViolation)
+               NOTIFY_CODE_HANDLER(CDN_TYPECHANGE, _OnTypeChange)
+#ifndef _WIN32_WCE
+               NOTIFY_CODE_HANDLER(CDN_INCLUDEITEM, _OnIncludeItem)
+#endif // !_WIN32_WCE
+       END_MSG_MAP()
+
+       LRESULT _OnFileOK(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               return !pT->OnFileOK((LPOFNOTIFY)pnmh);
+       }
+
+       LRESULT _OnFolderChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               pT->OnFolderChange((LPOFNOTIFY)pnmh);
+               return 0;
+       }
+
+       LRESULT _OnHelp(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               pT->OnHelp((LPOFNOTIFY)pnmh);
+               return 0;
+       }
+
+       LRESULT _OnInitDone(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               pT->OnInitDone((LPOFNOTIFY)pnmh);
+               return 0;
+       }
+
+       LRESULT _OnSelChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               pT->OnSelChange((LPOFNOTIFY)pnmh);
+               return 0;
+       }
+
+       LRESULT _OnShareViolation(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               return pT->OnShareViolation((LPOFNOTIFY)pnmh);
+       }
+
+       LRESULT _OnTypeChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               pT->OnTypeChange((LPOFNOTIFY)pnmh);
+               return 0;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT _OnIncludeItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               T* pT = static_cast<T*>(this);
+               return pT->OnIncludeItem((LPOFNOTIFYEX)pnmh);
+       }
+#endif // !_WIN32_WCE
+
+// Overrideables
+       BOOL OnFileOK(LPOFNOTIFY /*lpon*/)
+       {
+               return TRUE;
+       }
+
+       void OnFolderChange(LPOFNOTIFY /*lpon*/)
+       {
+       }
+
+       void OnHelp(LPOFNOTIFY /*lpon*/)
+       {
+       }
+
+       void OnInitDone(LPOFNOTIFY /*lpon*/)
+       {
+       }
+
+       void OnSelChange(LPOFNOTIFY /*lpon*/)
+       {
+       }
+
+       int OnShareViolation(LPOFNOTIFY /*lpon*/)
+       {
+               return 0;
+       }
+
+       void OnTypeChange(LPOFNOTIFY /*lpon*/)
+       {
+       }
+
+#ifndef _WIN32_WCE
+       BOOL OnIncludeItem(LPOFNOTIFYEX /*lponex*/)
+       {
+               return TRUE;   // include item
+       }
+#endif // !_WIN32_WCE
+};
+
+class CFileDialog : public CFileDialogImpl<CFileDialog>
+{
+public:
+       CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
+               LPCTSTR lpszDefExt = NULL,
+               LPCTSTR lpszFileName = NULL,
+               DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
+               LPCTSTR lpszFilter = NULL,
+               HWND hWndParent = NULL)
+               : CFileDialogImpl<CFileDialog>(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
+       { }
+
+       // override base class map and references to handlers
+       DECLARE_EMPTY_MSG_MAP()
+};
+
+#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
+class CFileDialogEx : public CFileDialogImpl<CFileDialogEx>
+{
+public:
+       CFileDialogEx( // Supports only FileOpen
+               LPCTSTR lpszDefExt = NULL,
+               LPCTSTR lpszFileName = NULL,
+               DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
+               OFN_EXFLAG ExFlags = OFN_EXFLAG_THUMBNAILVIEW,
+               OFN_SORTORDER dwSortOrder = OFN_SORTORDER_AUTO,         
+               LPCTSTR lpszFilter = NULL,
+               HWND hWndParent = NULL)
+               : CFileDialogImpl<CFileDialogEx>(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
+       {
+               m_ofn.ExFlags = ExFlags;
+               m_ofn.dwSortOrder = dwSortOrder;
+       }
+
+       // override base class map and references to handlers
+       DECLARE_EMPTY_MSG_MAP()
+};
+#endif // defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Multi File Dialog - Multi-select File Open dialog
+
+#ifndef _WIN32_WCE
+
+// The class dynamically resizes the buffer as the file selection changes
+// (as described in Knowledge Base article 131462). It also expands selected
+// shortcut files to take into account the full path of the target file.
+// Note that this doesn't work on Win9x for the old style dialogs, as well as
+// on NT for non-Unicode builds. 
+
+#ifndef _WTL_FIXED_OFN_BUFFER_LENGTH
+  #define _WTL_FIXED_OFN_BUFFER_LENGTH 0x10000
+#endif
+
+template <class T>
+class ATL_NO_VTABLE CMultiFileDialogImpl : public CFileDialogImpl< T >
+{
+public:
+       mutable LPCTSTR m_pNextFile; 
+#ifndef _UNICODE
+       bool m_bIsNT;
+#endif
+
+       CMultiFileDialogImpl(
+               LPCTSTR lpszDefExt = NULL,
+               LPCTSTR lpszFileName = NULL,
+               DWORD dwFlags = OFN_HIDEREADONLY,
+               LPCTSTR lpszFilter = NULL,
+               HWND hWndParent = NULL)
+               : CFileDialogImpl<T>(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent), 
+                 m_pNextFile(NULL)
+       {
+               m_ofn.Flags |= OFN_ALLOWMULTISELECT;   // Force multiple selection mode
+
+#ifndef _UNICODE
+               OSVERSIONINFO ovi = { sizeof(ovi) };
+               ::GetVersionEx(&ovi);
+               m_bIsNT = (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT);
+               if (m_bIsNT)
+               {
+                       // On NT platforms, GetOpenFileNameA thunks to GetOpenFileNameW and there 
+                       // is absolutely nothing we can do except to start off with a large buffer.
+                       ATLVERIFY(ResizeFilenameBuffer(_WTL_FIXED_OFN_BUFFER_LENGTH));
+               }
+#endif
+       }
+
+       ~CMultiFileDialogImpl()
+       {
+               if (m_ofn.lpstrFile != m_szFileName)   // Free the buffer if we allocated it
+                       delete[] m_ofn.lpstrFile;
+       }
+
+// Operations
+       // Get the directory that the files were chosen from.
+       // The function returns the number of characters copied, not including the terminating zero. 
+       // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
+       // If the function fails, the return value is zero.
+       int GetDirectory(LPTSTR pBuffer, int nBufLen) const
+       {
+               if (m_ofn.lpstrFile == NULL)
+                       return 0;
+
+               LPCTSTR pStr = m_ofn.lpstrFile;
+               int nLength = lstrlen(pStr);
+               if (pStr[nLength + 1] == 0)
+               {
+                       // The OFN buffer contains a single item so extract its path.
+                       LPCTSTR pSep = _strrchr(pStr, _T('\\'));
+                       if (pSep != NULL)
+                               nLength = (int)(DWORD_PTR)(pSep - pStr);
+               }
+
+               int nRet = 0;
+               if (pBuffer == NULL)   // If the buffer is NULL, return the required length
+               {
+                       nRet = nLength + 1;
+               }
+               else if (nBufLen > nLength)
+               {
+                       SecureHelper::strncpy_x(pBuffer, nBufLen, pStr, nLength);
+                       nRet = nLength;
+               }
+
+               return nRet;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       bool GetDirectory(_CSTRING_NS::CString& strDir) const
+       {
+               bool bRet = false;
+
+               int nLength = GetDirectory(NULL, 0);
+               if (nLength > 0)
+               {
+                       bRet = (GetDirectory(strDir.GetBuffer(nLength), nLength) > 0);
+                       strDir.ReleaseBuffer(nLength - 1);
+               }
+
+               return bRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       // Get the first filename as a pointer into the buffer.
+       LPCTSTR GetFirstFileName() const
+       {
+               if (m_ofn.lpstrFile == NULL)
+                       return NULL;
+
+               m_pNextFile = NULL;   // Reset internal buffer pointer
+
+               LPCTSTR pStr = m_ofn.lpstrFile;
+               int nLength = lstrlen(pStr);
+               if (pStr[nLength + 1] != 0)
+               {
+                       // Multiple items were selected. The first string is the directory,
+                       // so skip forwards to the second string.
+                       pStr += nLength + 1;
+
+                       // Set up m_pNext so it points to the second item (or null).
+                       m_pNextFile = pStr;
+                       GetNextFileName();
+               }
+               else
+               {
+                       // A single item was selected. Skip forward past the path.
+                       LPCTSTR pSep = _strrchr(pStr, _T('\\'));
+                       if (pSep != NULL)
+                               pStr = pSep + 1;
+               }
+
+               return pStr;
+       }
+
+       // Get the next filename as a pointer into the buffer.
+       LPCTSTR GetNextFileName() const
+       {
+               if (m_pNextFile == NULL)
+                       return NULL;
+
+               LPCTSTR pStr = m_pNextFile;
+               // Set "m_pNextFile" to point to the next file name, or null if we 
+               // have reached the last file in the list.
+               int nLength = lstrlen(pStr);
+               m_pNextFile = (pStr[nLength + 1] != 0) ? &pStr[nLength + 1] : NULL;
+
+               return pStr;
+       }
+
+       // Get the first filename as a full path.
+       // The function returns the number of characters copied, not including the terminating zero. 
+       // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
+       // If the function fails, the return value is zero.
+       int GetFirstPathName(LPTSTR pBuffer, int nBufLen) const
+       {
+               LPCTSTR pStr = GetFirstFileName();
+               int nLengthDir = GetDirectory(NULL, 0);
+               if((pStr == NULL) || (nLengthDir == 0))
+                       return 0;
+
+               // Figure out the required length.
+               int nLengthTotal = nLengthDir + lstrlen(pStr);
+
+               int nRet = 0;
+               if(pBuffer == NULL) // If the buffer is NULL, return the required length
+               {
+                       nRet = nLengthTotal + 1;
+               }
+               else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path
+               {               
+                       GetDirectory(pBuffer, nBufLen);
+                       SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\"));
+                       SecureHelper::strcat_x(pBuffer, nBufLen, pStr);
+                       nRet = nLengthTotal;
+               }
+
+               return nRet;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       bool GetFirstPathName(_CSTRING_NS::CString& strPath) const
+       {
+               bool bRet = false;
+
+               int nLength = GetFirstPathName(NULL, 0);
+               if (nLength > 0)
+               {
+                       bRet = (GetFirstPathName(strPath.GetBuffer(nLength), nLength) > 0);
+                       strPath.ReleaseBuffer(nLength - 1);
+               }
+
+               return bRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       // Get the next filename as a full path.
+       // The function returns the number of characters copied, not including the terminating zero. 
+       // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
+       // If the function fails, the return value is zero.
+       // The internal position marker is moved forward only if the function succeeds and the buffer was large enough.
+       int GetNextPathName(LPTSTR pBuffer, int nBufLen) const
+       {
+               if (m_pNextFile == NULL)
+                       return 0;
+
+               int nRet = 0;
+               LPCTSTR pStr = m_pNextFile;
+               // Does the filename contain a backslash?
+               if (_strrchr(pStr, _T('\\')) != NULL)
+               {
+                       // Yes, so we'll assume it's a full path.
+                       int nLength = lstrlen(pStr);
+
+                       if (pBuffer == NULL) // If the buffer is NULL, return the required length
+                       {
+                               nRet = nLength + 1;
+                       }
+                       else if (nBufLen > nLength) // The buffer is big enough, so go ahead and copy the filename
+                       {
+                               SecureHelper::strcpy_x(pBuffer, nBufLen, GetNextFileName());
+                               nRet = nBufLen;
+                       }
+               }
+               else
+               {
+                       // The filename is relative, so construct the full path.
+                       int nLengthDir = GetDirectory(NULL, 0);
+                       if (nLengthDir > 0)
+                       {
+                               // Calculate the required space.
+                               int nLengthTotal = nLengthDir + lstrlen(pStr);
+
+                               if(pBuffer == NULL) // If the buffer is NULL, return the required length
+                               {
+                                       nRet = nLengthTotal + 1;
+                               }
+                               else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path
+                               {
+                                       GetDirectory(pBuffer, nBufLen);
+                                       SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\"));
+                                       SecureHelper::strcat_x(pBuffer, nBufLen, GetNextFileName());
+                                       nRet = nLengthTotal;
+                               }
+                       }
+               }
+
+               return nRet;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       bool GetNextPathName(_CSTRING_NS::CString& strPath) const
+       {
+               bool bRet = false;
+
+               int nLength = GetNextPathName(NULL, 0);
+               if (nLength > 0)
+               {
+                       bRet = (GetNextPathName(strPath.GetBuffer(nLength), nLength) > 0);
+                       strPath.ReleaseBuffer(nLength - 1);
+               }
+
+               return bRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+// Implementation
+       bool ResizeFilenameBuffer(DWORD dwLength)
+       {
+               if (dwLength > m_ofn.nMaxFile)
+               {
+                       // Free the old buffer.
+                       if (m_ofn.lpstrFile != m_szFileName)
+                       {
+                               delete[] m_ofn.lpstrFile;
+                               m_ofn.lpstrFile = NULL;
+                               m_ofn.nMaxFile = 0;
+                       }
+
+                       // Allocate the new buffer.
+                       LPTSTR lpstrBuff = NULL;
+                       ATLTRY(lpstrBuff = new TCHAR[dwLength]);
+                       if (lpstrBuff != NULL)
+                       {
+                               m_ofn.lpstrFile = lpstrBuff;
+                               m_ofn.lpstrFile[0] = 0;
+                               m_ofn.nMaxFile = dwLength;
+                       }
+               }
+
+               return (m_ofn.lpstrFile != NULL);
+       }
+
+       void OnSelChange(LPOFNOTIFY /*lpon*/)
+       {
+#ifndef _UNICODE
+               // There is no point resizing the buffer in ANSI builds running on NT.
+               if (m_bIsNT)
+                       return;
+#endif
+
+               // Get the buffer length required to hold the spec.
+               int nLength = GetSpec(NULL, 0);
+               if (nLength <= 1)
+                       return; // no files are selected, presumably
+               
+               // Add room for the directory, and an extra terminating zero.
+               nLength += GetFolderPath(NULL, 0) + 1;
+
+               if (!ResizeFilenameBuffer(nLength))
+               {
+                       ATLASSERT(FALSE);
+                       return;
+               }
+
+               // If we are not following links then our work is done.
+               if ((m_ofn.Flags & OFN_NODEREFERENCELINKS) != 0)
+                       return;
+
+               // Get the file spec, which is the text in the edit control.
+               if (GetSpec(m_ofn.lpstrFile, m_ofn.nMaxFile) <= 0)
+                       return;
+               
+               // Get the ID-list of the current folder.
+               int nBytes = GetFolderIDList(NULL, 0);
+               CTempBuffer<ITEMIDLIST> idlist;
+               idlist.AllocateBytes(nBytes);
+               if ((nBytes <= 0) || (GetFolderIDList(idlist, nBytes) <= 0))
+                       return;
+
+               // First bind to the desktop folder, then to the current folder.
+               ATL::CComPtr<IShellFolder> pDesktop, pFolder;
+               if (FAILED(::SHGetDesktopFolder(&pDesktop)))
+                       return;
+               if (FAILED(pDesktop->BindToObject(idlist, NULL, IID_IShellFolder, (void**)&pFolder)))
+                       return;
+
+               // Work through the file spec, looking for quoted filenames. If we find a shortcut file, then 
+               // we need to add enough extra buffer space to hold its target path.
+               DWORD nExtraChars = 0;
+               bool bInsideQuotes = false;
+               LPCTSTR pAnchor = m_ofn.lpstrFile;
+               LPCTSTR pChar = m_ofn.lpstrFile;
+               for ( ; *pChar; ++pChar)
+               {
+                       // Look for quotation marks.
+                       if (*pChar == _T('\"'))
+                       {
+                               // We are either entering or leaving a passage of quoted text.
+                               bInsideQuotes = !bInsideQuotes;
+
+                               // Is it an opening or closing quote?
+                               if (bInsideQuotes)
+                               {
+                                       // We found an opening quote, so set "pAnchor" to the following character.
+                                       pAnchor = pChar + 1;
+                               }
+                               else // closing quote
+                               {
+                                       // Each quoted entity should be shorter than MAX_PATH.
+                                       if (pChar - pAnchor >= MAX_PATH)
+                                               return;
+
+                                       // Get the ID-list and attributes of the file.
+                                       USES_CONVERSION;
+                                       int nFileNameLength = (int)(DWORD_PTR)(pChar - pAnchor);
+                                       TCHAR szFileName[MAX_PATH];
+                                       SecureHelper::strncpy_x(szFileName, MAX_PATH, pAnchor, nFileNameLength);
+                                       LPITEMIDLIST pidl = NULL;
+                                       DWORD dwAttrib = SFGAO_LINK;
+                                       if (SUCCEEDED(pFolder->ParseDisplayName(NULL, NULL, T2W(szFileName), NULL, &pidl, &dwAttrib)))
+                                       {
+                                               // Is it a shortcut file?
+                                               if (dwAttrib & SFGAO_LINK)
+                                               {
+                                                       // Bind to its IShellLink interface.
+                                                       ATL::CComPtr<IShellLink> pLink;
+                                                       if (SUCCEEDED(pFolder->BindToObject(pidl, NULL, IID_IShellLink, (void**)&pLink)))
+                                                       {
+                                                               // Get the shortcut's target path.
+                                                               TCHAR szPath[MAX_PATH];
+                                                               if (SUCCEEDED(pLink->GetPath(szPath, MAX_PATH, NULL, 0)))
+                                                               {
+                                                                       // If the target path is longer than the shortcut name, then add on the number 
+                                                                       // of extra characters that are required.
+                                                                       int nNewLength = lstrlen(szPath);
+                                                                       if (nNewLength > nFileNameLength)
+                                                                               nExtraChars += nNewLength - nFileNameLength;
+                                                               }
+                                                       }
+                                               }
+
+                                               // Free the ID-list returned by ParseDisplayName.
+                                               ::CoTaskMemFree(pidl);
+                                       }
+                               }
+                       }
+               }
+
+               // If we need more space for shortcut targets, then reallocate.
+               if (nExtraChars > 0)
+                       ATLVERIFY(ResizeFilenameBuffer(m_ofn.nMaxFile + nExtraChars));
+       }
+
+       // Helper for _ATM_MIN_CRT
+       static const TCHAR* _strrchr(const TCHAR* p, TCHAR ch)
+       {
+#ifndef _ATL_MIN_CRT
+               return _tcsrchr(p, ch);
+#else // _ATL_MIN_CRT
+               const TCHAR* lpsz = NULL;
+               while (*p != 0)
+               {
+                       if (*p == ch)
+                               lpsz = p;
+                       p = ::CharNext(p);
+               }
+               return lpsz;
+#endif // _ATL_MIN_CRT
+       }
+};
+
+class CMultiFileDialog : public CMultiFileDialogImpl<CMultiFileDialog>
+{
+public:
+       CMultiFileDialog(
+               LPCTSTR lpszDefExt = NULL,
+               LPCTSTR lpszFileName = NULL,
+               DWORD dwFlags = OFN_HIDEREADONLY,
+               LPCTSTR lpszFilter = NULL,
+               HWND hWndParent = NULL)
+               : CMultiFileDialogImpl<CMultiFileDialog>(lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
+       { }
+
+       BEGIN_MSG_MAP(CMultiFileDialog)
+               CHAIN_MSG_MAP(CMultiFileDialogImpl<CMultiFileDialog>)
+       END_MSG_MAP()
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Shell File Dialog - new Shell File Open and Save dialogs in Vista
+
+// Note: Use GetPtr() to access dialog interface methods.
+// Example:
+//     CShellFileOpenDialog dlg;
+//     dlg.GetPtr()->SetTitle(L"MyFileOpenDialog");
+
+#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
+
+///////////////////////////////////////////////////////////////////////////////
+// CShellFileDialogImpl - base class for CShellFileOpenDialogImpl and CShellFileSaveDialogImpl
+
+template <class T>
+class ATL_NO_VTABLE CShellFileDialogImpl : public IFileDialogEvents
+{
+public:
+// Operations
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               INT_PTR nRet = -1;
+
+               T* pT = static_cast<T*>(this);
+               if(pT->m_spFileDlg == NULL)
+               {
+                       ATLASSERT(FALSE);
+                       return nRet;
+               }
+
+               DWORD dwCookie = 0;
+               pT->_Advise(dwCookie);
+
+               HRESULT hRet = pT->m_spFileDlg->Show(hWndParent);
+               if(SUCCEEDED(hRet))
+                       nRet = IDOK;
+               else if(hRet == HRESULT_FROM_WIN32(ERROR_CANCELLED))
+                       nRet = IDCANCEL;
+               else
+                       ATLASSERT(FALSE);   // error
+
+               pT->_Unadvise(dwCookie);
+
+               return nRet;
+       }
+
+       bool IsNull() const
+       {
+               const T* pT = static_cast<const T*>(this);
+               return (pT->m_spFileDlg == NULL);
+       }
+
+// Operations - get file path after dialog returns
+       HRESULT GetFilePath(LPWSTR lpstrFilePath, int cchLength)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg != NULL);
+
+               ATL::CComPtr<IShellItem> spItem;
+               HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
+
+               if(SUCCEEDED(hRet))
+                       hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, lpstrFilePath, cchLength);
+
+               return hRet;
+       }
+
+       HRESULT GetFileTitle(LPWSTR lpstrFileTitle, int cchLength)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg != NULL);
+
+               ATL::CComPtr<IShellItem> spItem;
+               HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
+
+               if(SUCCEEDED(hRet))
+                       hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, lpstrFileTitle, cchLength);
+
+               return hRet;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       HRESULT GetFilePath(_CSTRING_NS::CString& strFilePath)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg != NULL);
+
+               ATL::CComPtr<IShellItem> spItem;
+               HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
+
+               if(SUCCEEDED(hRet))
+                       hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, strFilePath);
+
+               return hRet;
+       }
+
+       HRESULT GetFileTitle(_CSTRING_NS::CString& strFileTitle)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg != NULL);
+
+               ATL::CComPtr<IShellItem> spItem;
+               HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
+
+               if(SUCCEEDED(hRet))
+                       hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, strFileTitle);
+
+               return hRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+// Helpers for IShellItem
+       static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, LPWSTR lpstr, int cchLength)
+       {
+               ATLASSERT(pShellItem != NULL);
+
+               LPWSTR lpstrName = NULL;
+               HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName);
+
+               if(SUCCEEDED(hRet))
+               {
+                       if(lstrlenW(lpstrName) < cchLength)
+                       {
+                               SecureHelper::strcpyW_x(lpstr, cchLength, lpstrName);
+                       }
+                       else
+                       {
+                               ATLASSERT(FALSE);
+                               hRet = DISP_E_BUFFERTOOSMALL;
+                       }
+
+                       ::CoTaskMemFree(lpstrName);
+               }
+
+               return hRet;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, _CSTRING_NS::CString& str)
+       {
+               ATLASSERT(pShellItem != NULL);
+
+               LPWSTR lpstrName = NULL;
+               HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName);
+
+               if(SUCCEEDED(hRet))
+               {
+                       str = lpstrName;
+                       ::CoTaskMemFree(lpstrName);
+               }
+
+               return hRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+// Implementation
+       void _Advise(DWORD& dwCookie)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg != NULL);
+               HRESULT hRet = pT->m_spFileDlg->Advise((IFileDialogEvents*)this, &dwCookie);
+               ATLVERIFY(SUCCEEDED(hRet));
+       }
+
+       void _Unadvise(DWORD dwCookie)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg != NULL);
+               HRESULT hRet = pT->m_spFileDlg->Unadvise(dwCookie);
+               ATLVERIFY(SUCCEEDED(hRet));
+       }
+
+       void _Init(LPCWSTR lpszFileName, DWORD dwOptions, LPCWSTR lpszDefExt, const COMDLG_FILTERSPEC* arrFilterSpec, UINT uFilterSpecCount)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg != NULL);
+
+               HRESULT hRet = E_FAIL;
+
+               if(lpszFileName != NULL)
+               {
+                       hRet = pT->m_spFileDlg->SetFileName(lpszFileName);
+                       ATLASSERT(SUCCEEDED(hRet));
+               }
+
+               hRet = pT->m_spFileDlg->SetOptions(dwOptions);
+               ATLASSERT(SUCCEEDED(hRet));
+
+               if(lpszDefExt != NULL)
+               {
+                       hRet = pT->m_spFileDlg->SetDefaultExtension(lpszDefExt);
+                       ATLASSERT(SUCCEEDED(hRet));
+               }
+
+               if(arrFilterSpec != NULL && uFilterSpecCount != 0U)
+               {
+                       hRet = pT->m_spFileDlg->SetFileTypes(uFilterSpecCount, arrFilterSpec);
+                       ATLASSERT(SUCCEEDED(hRet));
+               }
+       }
+
+// Implementation - IUnknown interface
+       STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
+       {
+               if(ppvObject == NULL)
+                       return E_POINTER;
+
+               T* pT = static_cast<T*>(this);
+               if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogEvents))
+               {
+                       *ppvObject = (IFileDialogEvents*)pT;
+                       // AddRef() not needed
+                       return S_OK;
+               }
+
+               return E_NOINTERFACE;
+       }
+
+       virtual ULONG STDMETHODCALLTYPE AddRef()
+       {
+               return 1;
+       }
+
+       virtual ULONG STDMETHODCALLTYPE Release()
+       {
+               return 1;
+       }
+
+// Implementation - IFileDialogEvents interface
+       virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFileOk(IFileDialog* pfd)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
+               pfd;   // avoid level 4 warning
+               return pT->OnFileOk();
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChanging(IFileDialog* pfd, IShellItem* psiFolder)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
+               pfd;   // avoid level 4 warning
+               return pT->OnFolderChanging(psiFolder);
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChange(IFileDialog* pfd)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
+               pfd;   // avoid level 4 warning
+               return pT->OnFolderChange();
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnSelectionChange(IFileDialog* pfd)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
+               pfd;   // avoid level 4 warning
+               return pT->OnSelectionChange();
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnShareViolation(IFileDialog* pfd, IShellItem* psi, FDE_SHAREVIOLATION_RESPONSE* pResponse)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
+               pfd;   // avoid level 4 warning
+               return pT->OnShareViolation(psi, pResponse);
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnTypeChange(IFileDialog* pfd)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
+               pfd;   // avoid level 4 warning
+               return pT->OnTypeChange();
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnOverwrite(IFileDialog* pfd, IShellItem* psi, FDE_OVERWRITE_RESPONSE* pResponse)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
+               pfd;   // avoid level 4 warning
+               return pT->OnOverwrite(psi, pResponse);
+       }
+
+// Overrideables - Event handlers
+       HRESULT OnFileOk()
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT OnFolderChanging(IShellItem* /*psiFolder*/)
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT OnFolderChange()
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT OnSelectionChange()
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT OnShareViolation(IShellItem* /*psi*/, FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/)
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT OnTypeChange()
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT OnOverwrite(IShellItem* /*psi*/, FDE_OVERWRITE_RESPONSE* /*pResponse*/)
+       {
+               return E_NOTIMPL;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CShellFileOpenDialogImpl - implements new Shell File Open dialog
+
+template <class T>
+class ATL_NO_VTABLE CShellFileOpenDialogImpl : public CShellFileDialogImpl< T >
+{
+public:
+       ATL::CComPtr<IFileOpenDialog> m_spFileDlg;
+
+       CShellFileOpenDialogImpl(LPCWSTR lpszFileName = NULL, 
+                                DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, 
+                                LPCWSTR lpszDefExt = NULL, 
+                                const COMDLG_FILTERSPEC* arrFilterSpec = NULL, 
+                                UINT uFilterSpecCount = 0U)
+       {
+               HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileOpenDialog);
+
+               if(SUCCEEDED(hRet))
+                       _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
+       }
+
+       IFileOpenDialog* GetPtr()
+       {
+               return m_spFileDlg;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CShellFileOpenDialog - new Shell File Open dialog without events
+
+class CShellFileOpenDialog : public CShellFileOpenDialogImpl<CShellFileOpenDialog>
+{
+public:
+       CShellFileOpenDialog(LPCWSTR lpszFileName = NULL, 
+                            DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, 
+                            LPCWSTR lpszDefExt = NULL, 
+                            const COMDLG_FILTERSPEC* arrFilterSpec = NULL, 
+                            UINT uFilterSpecCount = 0U) : CShellFileOpenDialogImpl<CShellFileOpenDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
+       { }
+
+// Implementation (remove _Advise/_Unadvise code using template magic)
+       void _Advise(DWORD& /*dwCookie*/)
+       { }
+
+       void _Unadvise(DWORD /*dwCookie*/)
+       { }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CShellFileSaveDialogImpl - implements new Shell File Save dialog
+
+template <class T>
+class ATL_NO_VTABLE CShellFileSaveDialogImpl : public CShellFileDialogImpl< T >
+{
+public:
+       ATL::CComPtr<IFileSaveDialog> m_spFileDlg;
+
+       CShellFileSaveDialogImpl(LPCWSTR lpszFileName = NULL, 
+                                DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT, 
+                                LPCWSTR lpszDefExt = NULL, 
+                                const COMDLG_FILTERSPEC* arrFilterSpec = NULL, 
+                                UINT uFilterSpecCount = 0U)
+       {
+               HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileSaveDialog);
+
+               if(SUCCEEDED(hRet))
+                       _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
+       }
+
+       IFileSaveDialog* GetPtr()
+       {
+               return m_spFileDlg;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CShellFileSaveDialog - new Shell File Save dialog without events
+
+class CShellFileSaveDialog : public CShellFileSaveDialogImpl<CShellFileSaveDialog>
+{
+public:
+       CShellFileSaveDialog(LPCWSTR lpszFileName = NULL, 
+                            DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT, 
+                            LPCWSTR lpszDefExt = NULL, 
+                            const COMDLG_FILTERSPEC* arrFilterSpec = NULL, 
+                            UINT uFilterSpecCount = 0U) : CShellFileSaveDialogImpl<CShellFileSaveDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
+       { }
+
+// Implementation (remove _Advise/_Unadvise code using template magic)
+       void _Advise(DWORD& /*dwCookie*/)
+       { }
+
+       void _Unadvise(DWORD /*dwCookie*/)
+       { }
+};
+
+#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CFolderDialogImpl - used for browsing for a folder
+
+#ifndef _WIN32_WCE
+
+template <class T>
+class ATL_NO_VTABLE CFolderDialogImpl
+{
+public:
+       BROWSEINFO m_bi;
+       LPCTSTR m_lpstrInitialFolder;
+       LPCITEMIDLIST m_pidlInitialSelection;
+       bool m_bExpandInitialSelection;
+       TCHAR m_szFolderDisplayName[MAX_PATH];
+       TCHAR m_szFolderPath[MAX_PATH];
+       LPITEMIDLIST m_pidlSelected;
+       HWND m_hWnd;   // used only in the callback function
+
+// Constructor
+       CFolderDialogImpl(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS) : 
+                       m_lpstrInitialFolder(NULL), m_pidlInitialSelection(NULL), m_bExpandInitialSelection(false), m_pidlSelected(NULL), m_hWnd(NULL)
+       {
+               memset(&m_bi, 0, sizeof(m_bi)); // initialize structure to 0/NULL
+
+               m_bi.hwndOwner = hWndParent;
+               m_bi.pidlRoot = NULL;
+               m_bi.pszDisplayName = m_szFolderDisplayName;
+               m_bi.lpszTitle = lpstrTitle;
+               m_bi.ulFlags = uFlags;
+               m_bi.lpfn = BrowseCallbackProc;
+               m_bi.lParam = (LPARAM)static_cast<T*>(this);
+
+               m_szFolderPath[0] = 0;
+               m_szFolderDisplayName[0] = 0;
+       }
+
+       ~CFolderDialogImpl()
+       {
+               ::CoTaskMemFree(m_pidlSelected);
+       }
+
+// Operations
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               if(m_bi.hwndOwner == NULL)   // set only if not specified before
+                       m_bi.hwndOwner = hWndParent;
+
+               // Clear out any previous results
+               m_szFolderPath[0] = 0;
+               m_szFolderDisplayName[0] = 0;
+               ::CoTaskMemFree(m_pidlSelected);
+
+               INT_PTR nRet = IDCANCEL;
+               m_pidlSelected = ::SHBrowseForFolder(&m_bi);
+
+               if(m_pidlSelected != NULL)
+               {
+                       nRet = IDOK;
+
+                       // If BIF_RETURNONLYFSDIRS is set, we try to get the filesystem path.
+                       // Otherwise, the caller must handle the ID-list directly.
+                       if((m_bi.ulFlags & BIF_RETURNONLYFSDIRS) != 0)
+                       {
+                               if(::SHGetPathFromIDList(m_pidlSelected, m_szFolderPath) == FALSE)
+                                       nRet = IDCANCEL;
+                       }
+               }
+
+               return nRet;
+       }
+
+       // Methods to call before DoModal
+       void SetInitialFolder(LPCTSTR lpstrInitialFolder, bool bExpand = true)
+       {
+               // lpstrInitialFolder may be a file if BIF_BROWSEINCLUDEFILES is specified
+               m_lpstrInitialFolder = lpstrInitialFolder;
+               m_bExpandInitialSelection = bExpand;
+       }
+
+       void SetInitialSelection(LPCITEMIDLIST pidl, bool bExpand = true)
+       {
+               m_pidlInitialSelection = pidl;
+               m_bExpandInitialSelection = bExpand;
+       }
+
+       // Methods to call after DoModal
+       LPITEMIDLIST GetSelectedItem(bool bDetach = false)
+       {
+               LPITEMIDLIST pidl = m_pidlSelected;
+               if(bDetach)
+                       m_pidlSelected = NULL;
+
+               return pidl;
+       }
+
+       LPCTSTR GetFolderPath() const
+       {
+               return m_szFolderPath;
+       }
+
+       LPCTSTR GetFolderDisplayName() const
+       {
+               return m_szFolderDisplayName;
+       }
+
+       int GetFolderImageIndex() const
+       {
+               return m_bi.iImage;
+       }
+
+// Callback function and overrideables
+       static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
+       {
+#ifndef BFFM_VALIDATEFAILED
+  #ifdef UNICODE
+               const int BFFM_VALIDATEFAILED = 4;
+  #else
+               const int BFFM_VALIDATEFAILED = 3;
+  #endif
+#endif // !BFFM_VALIDATEFAILED
+#ifndef BFFM_IUNKNOWN
+               const int BFFM_IUNKNOWN = 5;
+#endif // !BFFM_IUNKNOWN
+#ifndef BIF_NEWDIALOGSTYLE
+               const UINT BIF_NEWDIALOGSTYLE = 0x0040;
+#endif // !BIF_NEWDIALOGSTYLE
+
+               int nRet = 0;
+               T* pT = (T*)lpData;
+               bool bClear = false;
+               if(pT->m_hWnd == NULL)
+               {
+                       pT->m_hWnd = hWnd;
+                       bClear = true;
+               }
+               else
+               {
+                       ATLASSERT(pT->m_hWnd == hWnd);
+               }
+
+               switch(uMsg)
+               {
+               case BFFM_INITIALIZED:
+                       // Set initial selection
+                       // Note that m_pidlInitialSelection, if set, takes precedence over m_lpstrInitialFolder
+                       if(pT->m_pidlInitialSelection != NULL)
+                               pT->SetSelection(pT->m_pidlInitialSelection);
+                       else if(pT->m_lpstrInitialFolder != NULL)
+                               pT->SetSelection(pT->m_lpstrInitialFolder);
+
+                       // Expand initial selection if appropriate
+                       if(pT->m_bExpandInitialSelection && ((pT->m_bi.ulFlags & BIF_NEWDIALOGSTYLE) != 0))
+                       {
+                               if(pT->m_pidlInitialSelection != NULL)
+                                       pT->SetExpanded(pT->m_pidlInitialSelection);
+                               else if(pT->m_lpstrInitialFolder != NULL)
+                                       pT->SetExpanded(pT->m_lpstrInitialFolder);
+                       }
+                       pT->OnInitialized();
+                       break;
+               case BFFM_SELCHANGED:
+                       pT->OnSelChanged((LPITEMIDLIST)lParam);
+                       break;
+               case BFFM_VALIDATEFAILED:
+                       nRet = pT->OnValidateFailed((LPCTSTR)lParam);
+                       break;
+               case BFFM_IUNKNOWN:
+                       pT->OnIUnknown((IUnknown*)lParam);
+                       break;
+               default:
+                       ATLTRACE2(atlTraceUI, 0, _T("Unknown message received in CFolderDialogImpl::BrowseCallbackProc\n"));
+                       break;
+               }
+
+               if(bClear)
+                       pT->m_hWnd = NULL;
+               return nRet;
+       }
+
+       void OnInitialized()
+       {
+       }
+
+       void OnSelChanged(LPITEMIDLIST /*pItemIDList*/)
+       {
+       }
+
+       int OnValidateFailed(LPCTSTR /*lpstrFolderPath*/)
+       {
+               return 1;   // 1=continue, 0=EndDialog
+       }
+
+       void OnIUnknown(IUnknown* /*pUnknown*/)
+       {
+       }
+
+       // Commands - valid to call only from handlers
+       void EnableOK(BOOL bEnable)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, BFFM_ENABLEOK, 0, bEnable);
+       }
+
+       void SetSelection(LPCITEMIDLIST pItemIDList)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pItemIDList);
+       }
+
+       void SetSelection(LPCTSTR lpstrFolderPath)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrFolderPath);
+       }
+
+       void SetStatusText(LPCTSTR lpstrText)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)lpstrText);
+       }
+
+       void SetOKText(LPCTSTR lpstrOKText)
+       {
+#ifndef BFFM_SETOKTEXT
+               const UINT BFFM_SETOKTEXT = WM_USER + 105;
+#endif
+               ATLASSERT(m_hWnd != NULL);
+               USES_CONVERSION;
+               LPCWSTR lpstr = T2CW(lpstrOKText);
+               ::SendMessage(m_hWnd, BFFM_SETOKTEXT, (WPARAM)lpstr, 0L);
+       }
+
+       void SetExpanded(LPCITEMIDLIST pItemIDList)
+       {
+#ifndef BFFM_SETEXPANDED
+               const UINT BFFM_SETEXPANDED = WM_USER + 106;
+#endif
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, BFFM_SETEXPANDED, FALSE, (LPARAM)pItemIDList);
+       }
+
+       void SetExpanded(LPCTSTR lpstrFolderPath)
+       {
+#ifndef BFFM_SETEXPANDED
+               const UINT BFFM_SETEXPANDED = WM_USER + 106;
+#endif
+               ATLASSERT(m_hWnd != NULL);
+               USES_CONVERSION;
+               LPCWSTR lpstr = T2CW(lpstrFolderPath);
+               ::SendMessage(m_hWnd, BFFM_SETEXPANDED, TRUE, (LPARAM)lpstr);
+       }
+};
+
+class CFolderDialog : public CFolderDialogImpl<CFolderDialog>
+{
+public:
+       CFolderDialog(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS)
+               : CFolderDialogImpl<CFolderDialog>(hWndParent, lpstrTitle, uFlags)
+       { }
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CCommonDialogImplBase - base class for common dialog classes
+
+class ATL_NO_VTABLE CCommonDialogImplBase : public ATL::CWindowImplBase
+{
+public:
+       static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               if(uMsg != WM_INITDIALOG)
+                       return 0;
+               CCommonDialogImplBase* pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData();
+               ATLASSERT(pT != NULL);
+               ATLASSERT(pT->m_hWnd == NULL);
+               ATLASSERT(::IsWindow(hWnd));
+               // subclass dialog's window
+               if(!pT->SubclassWindow(hWnd))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("Subclassing a common dialog failed\n"));
+                       return 0;
+               }
+               // check message map for WM_INITDIALOG handler
+               LRESULT lRes = 0;
+               if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
+                       return 0;
+               return lRes;
+       }
+
+// Special override for common dialogs
+       BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
+               return TRUE;
+       }
+
+// Implementation - try to override these, to prevent errors
+       HWND Create(HWND, ATL::_U_RECT, LPCTSTR, DWORD, DWORD, ATL::_U_MENUorID, ATOM, LPVOID)
+       {
+               ATLASSERT(FALSE);   // should not be called
+               return NULL;
+       }
+
+       static LRESULT CALLBACK StartWindowProc(HWND /*hWnd*/, UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
+       {
+               ATLASSERT(FALSE);   // should not be called
+               return 0;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CFontDialogImpl - font selection dialog
+
+#ifndef _WIN32_WCE
+
+template <class T>
+class ATL_NO_VTABLE CFontDialogImpl : public CCommonDialogImplBase
+{
+public:
+       enum { _cchStyleName = 64 };
+
+       CHOOSEFONT m_cf;
+       TCHAR m_szStyleName[_cchStyleName];  // contains style name after return
+       LOGFONT m_lf;                        // default LOGFONT to store the info
+
+// Constructors
+       CFontDialogImpl(LPLOGFONT lplfInitial = NULL,
+                       DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
+                       HDC hDCPrinter = NULL,
+                       HWND hWndParent = NULL)
+       {
+               memset(&m_cf, 0, sizeof(m_cf));
+               memset(&m_lf, 0, sizeof(m_lf));
+               memset(&m_szStyleName, 0, sizeof(m_szStyleName));
+
+               m_cf.lStructSize = sizeof(m_cf);
+               m_cf.hwndOwner = hWndParent;
+               m_cf.rgbColors = RGB(0, 0, 0);
+               m_cf.lpszStyle = (LPTSTR)&m_szStyleName;
+               m_cf.Flags = dwFlags | CF_ENABLEHOOK;
+               m_cf.lpfnHook = (LPCFHOOKPROC)T::HookProc;
+
+               if(lplfInitial != NULL)
+               {
+                       m_cf.lpLogFont = lplfInitial;
+                       m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
+                       m_lf = *lplfInitial;
+               }
+               else
+               {
+                       m_cf.lpLogFont = &m_lf;
+               }
+
+               if(hDCPrinter != NULL)
+               {
+                       m_cf.hDC = hDCPrinter;
+                       m_cf.Flags |= CF_PRINTERFONTS;
+               }
+       }
+
+// Operations
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               ATLASSERT((m_cf.Flags & CF_ENABLEHOOK) != 0);
+               ATLASSERT(m_cf.lpfnHook != NULL);   // can still be a user hook
+
+               if(m_cf.hwndOwner == NULL)          // set only if not specified before
+                       m_cf.hwndOwner = hWndParent;
+
+               ATLASSERT(m_hWnd == NULL);
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
+
+               BOOL bRet = ::ChooseFont(&m_cf);
+
+               m_hWnd = NULL;
+
+               if(bRet)   // copy logical font from user's initialization buffer (if needed)
+                       SecureHelper::memcpy_x(&m_lf, sizeof(m_lf), m_cf.lpLogFont, sizeof(m_lf));
+
+               return bRet ? IDOK : IDCANCEL;
+       }
+
+       // works only when the dialog is dislayed or after
+       void GetCurrentFont(LPLOGFONT lplf) const
+       {
+               ATLASSERT(lplf != NULL);
+
+               if(m_hWnd != NULL)
+                       ::SendMessage(m_hWnd, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM)lplf);
+               else
+                       *lplf = m_lf;
+       }
+
+       // works only when the dialog is dislayed or before
+#ifndef _WIN32_WCE
+       void SetLogFont(LPLOGFONT lplf)
+       {
+               ATLASSERT(lplf != NULL);
+#ifndef WM_CHOOSEFONT_SETLOGFONT
+               const UINT WM_CHOOSEFONT_SETLOGFONT = (WM_USER + 101);
+#endif
+               if(m_hWnd != NULL)
+               {
+                       ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETLOGFONT, 0, (LPARAM)lplf);
+               }
+               else
+               {
+                       m_lf = *lplf;
+                       m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
+               }
+       }
+
+       void SetFlags(DWORD dwFlags)
+       {
+#ifndef WM_CHOOSEFONT_SETFLAGS
+               const UINT WM_CHOOSEFONT_SETFLAGS = (WM_USER + 102);
+#endif
+               if(m_hWnd != NULL)
+               {
+                       CHOOSEFONT cf = { sizeof(CHOOSEFONT) };
+                       cf.Flags = dwFlags;
+                       ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETFLAGS, 0, (LPARAM)&cf);
+               }
+               else
+               {
+                       m_cf.Flags = dwFlags;
+               }
+       }
+#endif // !_WIN32_WCE
+
+       // Helpers for parsing information after successful return
+       LPCTSTR GetFaceName() const   // return the face name of the font
+       {
+               return (LPCTSTR)m_cf.lpLogFont->lfFaceName;
+       }
+
+       LPCTSTR GetStyleName() const  // return the style name of the font
+       {
+               return m_cf.lpszStyle;
+       }
+
+       int GetSize() const           // return the pt size of the font
+       {
+               return m_cf.iPointSize;
+       }
+
+       COLORREF GetColor() const     // return the color of the font
+       {
+               return m_cf.rgbColors;
+       }
+
+       int GetWeight() const         // return the chosen font weight
+       {
+               return (int)m_cf.lpLogFont->lfWeight;
+       }
+
+       BOOL IsStrikeOut() const      // return TRUE if strikeout
+       {
+               return (m_cf.lpLogFont->lfStrikeOut) ? TRUE : FALSE;
+       }
+
+       BOOL IsUnderline() const      // return TRUE if underline
+       {
+               return (m_cf.lpLogFont->lfUnderline) ? TRUE : FALSE;
+       }
+
+       BOOL IsBold() const           // return TRUE if bold font
+       {
+               return (m_cf.lpLogFont->lfWeight == FW_BOLD) ? TRUE : FALSE;
+       }
+
+       BOOL IsItalic() const         // return TRUE if italic font
+       {
+               return m_cf.lpLogFont->lfItalic ? TRUE : FALSE;
+       }
+};
+
+class CFontDialog : public CFontDialogImpl<CFontDialog>
+{
+public:
+       CFontDialog(LPLOGFONT lplfInitial = NULL,
+               DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
+               HDC hDCPrinter = NULL,
+               HWND hWndParent = NULL)
+               : CFontDialogImpl<CFontDialog>(lplfInitial, dwFlags, hDCPrinter, hWndParent)
+       { }
+
+       DECLARE_EMPTY_MSG_MAP()
+};
+
+#endif // _WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CRichEditFontDialogImpl - font selection for the Rich Edit ctrl
+
+#if defined(_RICHEDIT_) && !defined(_WIN32_WCE)
+
+template <class T>
+class ATL_NO_VTABLE CRichEditFontDialogImpl : public CFontDialogImpl< T >
+{
+public:
+       CRichEditFontDialogImpl(const CHARFORMAT& charformat,
+                       DWORD dwFlags = CF_SCREENFONTS,
+                       HDC hDCPrinter = NULL,
+                       HWND hWndParent = NULL)
+                       : CFontDialogImpl< T >(NULL, dwFlags, hDCPrinter, hWndParent)
+       {
+               m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
+               m_cf.Flags |= FillInLogFont(charformat);
+               m_cf.lpLogFont = &m_lf;
+
+               if((charformat.dwMask & CFM_COLOR) != 0)
+                       m_cf.rgbColors = charformat.crTextColor;
+       }
+
+       void GetCharFormat(CHARFORMAT& cf) const
+       {
+               USES_CONVERSION;
+               cf.dwEffects = 0;
+               cf.dwMask = 0;
+               if((m_cf.Flags & CF_NOSTYLESEL) == 0)
+               {
+                       cf.dwMask |= CFM_BOLD | CFM_ITALIC;
+                       cf.dwEffects |= IsBold() ? CFE_BOLD : 0;
+                       cf.dwEffects |= IsItalic() ? CFE_ITALIC : 0;
+               }
+               if((m_cf.Flags & CF_NOSIZESEL) == 0)
+               {
+                       cf.dwMask |= CFM_SIZE;
+                       // GetSize() returns in tenths of points so mulitply by 2 to get twips
+                       cf.yHeight = GetSize() * 2;
+               }
+
+               if((m_cf.Flags & CF_NOFACESEL) == 0)
+               {
+                       cf.dwMask |= CFM_FACE;
+                       cf.bPitchAndFamily = m_cf.lpLogFont->lfPitchAndFamily;
+#if (_RICHEDIT_VER >= 0x0200)
+                       SecureHelper::strcpy_x(cf.szFaceName, _countof(cf.szFaceName), GetFaceName());
+#else // !(_RICHEDIT_VER >= 0x0200)
+                       SecureHelper::strcpyA_x(cf.szFaceName, _countof(cf.szFaceName), T2A((LPTSTR)(LPCTSTR)GetFaceName()));
+#endif // !(_RICHEDIT_VER >= 0x0200)
+               }
+
+               if((m_cf.Flags & CF_EFFECTS) != 0)
+               {
+                       cf.dwMask |= CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR;
+                       cf.dwEffects |= IsUnderline() ? CFE_UNDERLINE : 0;
+                       cf.dwEffects |= IsStrikeOut() ? CFE_STRIKEOUT : 0;
+                       cf.crTextColor = GetColor();
+               }
+               if((m_cf.Flags & CF_NOSCRIPTSEL) == 0)
+               {
+                       cf.bCharSet = m_cf.lpLogFont->lfCharSet;
+                       cf.dwMask |= CFM_CHARSET;
+               }
+               cf.yOffset = 0;
+       }
+
+       DWORD FillInLogFont(const CHARFORMAT& cf)
+       {
+               USES_CONVERSION;
+               DWORD dwFlags = 0;
+               if((cf.dwMask & CFM_SIZE) != 0)
+               {
+                       HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
+                       LONG yPerInch = ::GetDeviceCaps(hDC, LOGPIXELSY);
+                       m_lf.lfHeight = -(int)((cf.yHeight * yPerInch) / 1440);
+               }
+               else
+                       m_lf.lfHeight = 0;
+
+               m_lf.lfWidth = 0;
+               m_lf.lfEscapement = 0;
+               m_lf.lfOrientation = 0;
+
+               if((cf.dwMask & (CFM_ITALIC | CFM_BOLD)) == (CFM_ITALIC | CFM_BOLD))
+               {
+                       m_lf.lfWeight = ((cf.dwEffects & CFE_BOLD) != 0) ? FW_BOLD : FW_NORMAL;
+                       m_lf.lfItalic = (BYTE)(((cf.dwEffects & CFE_ITALIC) != 0) ? TRUE : FALSE);
+               }
+               else
+               {
+                       dwFlags |= CF_NOSTYLESEL;
+                       m_lf.lfWeight = FW_DONTCARE;
+                       m_lf.lfItalic = FALSE;
+               }
+
+               if((cf.dwMask & (CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR)) == (CFM_UNDERLINE|CFM_STRIKEOUT|CFM_COLOR))
+               {
+                       dwFlags |= CF_EFFECTS;
+                       m_lf.lfUnderline = (BYTE)(((cf.dwEffects & CFE_UNDERLINE) != 0) ? TRUE : FALSE);
+                       m_lf.lfStrikeOut = (BYTE)(((cf.dwEffects & CFE_STRIKEOUT) != 0) ? TRUE : FALSE);
+               }
+               else
+               {
+                       m_lf.lfUnderline = (BYTE)FALSE;
+                       m_lf.lfStrikeOut = (BYTE)FALSE;
+               }
+
+               if((cf.dwMask & CFM_CHARSET) != 0)
+                       m_lf.lfCharSet = cf.bCharSet;
+               else
+                       dwFlags |= CF_NOSCRIPTSEL;
+               m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+               m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+               m_lf.lfQuality = DEFAULT_QUALITY;
+               if((cf.dwMask & CFM_FACE) != 0)
+               {
+                       m_lf.lfPitchAndFamily = cf.bPitchAndFamily;
+#if (_RICHEDIT_VER >= 0x0200)
+                       SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), cf.szFaceName);
+#else // !(_RICHEDIT_VER >= 0x0200)
+                       SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), A2T((LPSTR)cf.szFaceName));
+#endif // !(_RICHEDIT_VER >= 0x0200)
+               }
+               else
+               {
+                       m_lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
+                       m_lf.lfFaceName[0] = (TCHAR)0;
+               }
+               return dwFlags;
+       }
+};
+
+class CRichEditFontDialog : public CRichEditFontDialogImpl<CRichEditFontDialog>
+{
+public:
+       CRichEditFontDialog(const CHARFORMAT& charformat,
+               DWORD dwFlags = CF_SCREENFONTS,
+               HDC hDCPrinter = NULL,
+               HWND hWndParent = NULL)
+               : CRichEditFontDialogImpl<CRichEditFontDialog>(charformat, dwFlags, hDCPrinter, hWndParent)
+       { }
+
+       DECLARE_EMPTY_MSG_MAP()
+};
+
+#endif // defined(_RICHEDIT_) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CColorDialogImpl - color selection
+
+#if !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500)))
+
+#ifdef _WIN32_WCE
+  #pragma comment(lib, "commdlg.lib")
+
+  #ifndef SETRGBSTRING
+    #define SETRGBSTRING _T("commdlg_SetRGBColor")
+  #endif
+
+  #ifndef COLOROKSTRING
+    #define COLOROKSTRING _T("commdlg_ColorOK")
+  #endif
+#endif
+
+template <class T>
+class ATL_NO_VTABLE CColorDialogImpl : public CCommonDialogImplBase
+{
+public:
+       CHOOSECOLOR m_cc;
+
+// Constructor
+       CColorDialogImpl(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
+       {
+               memset(&m_cc, 0, sizeof(m_cc));
+
+               m_cc.lStructSize = sizeof(m_cc);
+               m_cc.lpCustColors = GetCustomColors();
+               m_cc.hwndOwner = hWndParent;
+               m_cc.Flags = dwFlags | CC_ENABLEHOOK;
+               m_cc.lpfnHook = (LPCCHOOKPROC)T::HookProc;
+
+               if(clrInit != 0)
+               {
+                       m_cc.rgbResult = clrInit;
+                       m_cc.Flags |= CC_RGBINIT;
+               }
+       }
+
+// Operations
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               ATLASSERT((m_cc.Flags & CC_ENABLEHOOK) != 0);
+               ATLASSERT(m_cc.lpfnHook != NULL);   // can still be a user hook
+
+               if(m_cc.hwndOwner == NULL)          // set only if not specified before
+                       m_cc.hwndOwner = hWndParent;
+
+               ATLASSERT(m_hWnd == NULL);
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
+
+               BOOL bRet = ::ChooseColor(&m_cc);
+
+               m_hWnd = NULL;
+
+               return bRet ? IDOK : IDCANCEL;
+       }
+
+       // Set the current color while dialog is displayed
+       void SetCurrentColor(COLORREF clr)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               SendMessage(_GetSetRGBMessage(), 0, (LPARAM)clr);
+       }
+
+       // Get the selected color after DoModal returns, or in OnColorOK
+       COLORREF GetColor() const
+       {
+               return m_cc.rgbResult;
+       }
+
+// Special override for the color dialog
+       static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               if(uMsg != WM_INITDIALOG && uMsg != _GetColorOKMessage())
+                       return 0;
+
+               LPCHOOSECOLOR lpCC = (LPCHOOSECOLOR)lParam;
+               CCommonDialogImplBase* pT = NULL;
+
+               if(uMsg == WM_INITDIALOG)
+               {
+                       pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData();
+                       lpCC->lCustData = (LPARAM)pT;
+                       ATLASSERT(pT != NULL);
+                       ATLASSERT(pT->m_hWnd == NULL);
+                       ATLASSERT(::IsWindow(hWnd));
+                       // subclass dialog's window
+                       if(!pT->SubclassWindow(hWnd))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("Subclassing a Color common dialog failed\n"));
+                               return 0;
+                       }
+               }
+               else if(uMsg == _GetColorOKMessage())
+               {
+                       pT = (CCommonDialogImplBase*)lpCC->lCustData;
+                       ATLASSERT(pT != NULL);
+                       ATLASSERT(::IsWindow(pT->m_hWnd));
+               }
+
+               // pass to the message map
+               LRESULT lRes;
+               if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
+                       return 0;
+               return lRes;
+       }
+
+// Helpers
+       static COLORREF* GetCustomColors()
+       {
+               static COLORREF rgbCustomColors[16] =
+               {
+                       RGB(255, 255, 255), RGB(255, 255, 255), 
+                       RGB(255, 255, 255), RGB(255, 255, 255), 
+                       RGB(255, 255, 255), RGB(255, 255, 255), 
+                       RGB(255, 255, 255), RGB(255, 255, 255), 
+                       RGB(255, 255, 255), RGB(255, 255, 255), 
+                       RGB(255, 255, 255), RGB(255, 255, 255), 
+                       RGB(255, 255, 255), RGB(255, 255, 255), 
+                       RGB(255, 255, 255), RGB(255, 255, 255), 
+               };
+
+               return rgbCustomColors;
+       }
+
+       static UINT _GetSetRGBMessage()
+       {
+               static UINT uSetRGBMessage = 0;
+               if(uSetRGBMessage == 0)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetSetRGBMessage.\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(uSetRGBMessage == 0)
+                               uSetRGBMessage = ::RegisterWindowMessage(SETRGBSTRING);
+
+                       lock.Unlock();
+               }
+               ATLASSERT(uSetRGBMessage != 0);
+               return uSetRGBMessage;
+       }
+
+       static UINT _GetColorOKMessage()
+       {
+               static UINT uColorOKMessage = 0;
+               if(uColorOKMessage == 0)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetColorOKMessage.\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(uColorOKMessage == 0)
+                               uColorOKMessage = ::RegisterWindowMessage(COLOROKSTRING);
+
+                       lock.Unlock();
+               }
+               ATLASSERT(uColorOKMessage != 0);
+               return uColorOKMessage;
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CColorDialogImpl)
+               MESSAGE_HANDLER(_GetColorOKMessage(), _OnColorOK)
+       END_MSG_MAP()
+
+       LRESULT _OnColorOK(UINT, WPARAM, LPARAM, BOOL&)
+       {
+               T* pT = static_cast<T*>(this);
+               return pT->OnColorOK();
+       }
+
+// Overrideable
+       BOOL OnColorOK()        // validate color
+       {
+               return FALSE;
+       }
+};
+
+class CColorDialog : public CColorDialogImpl<CColorDialog>
+{
+public:
+       CColorDialog(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
+               : CColorDialogImpl<CColorDialog>(clrInit, dwFlags, hWndParent)
+       { }
+
+       // override base class map and references to handlers
+       DECLARE_EMPTY_MSG_MAP()
+};
+
+#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500)))
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPrintDialogImpl - used for Print... and PrintSetup...
+
+#ifndef _WIN32_WCE
+
+// global helper
+static HDC _AtlCreateDC(HGLOBAL hDevNames, HGLOBAL hDevMode)
+{
+       if(hDevNames == NULL)
+               return NULL;
+
+       LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(hDevNames);
+       LPDEVMODE  lpDevMode = (hDevMode != NULL) ? (LPDEVMODE)::GlobalLock(hDevMode) : NULL;
+
+       if(lpDevNames == NULL)
+               return NULL;
+
+       HDC hDC = ::CreateDC((LPCTSTR)lpDevNames + lpDevNames->wDriverOffset,
+                                         (LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset,
+                                         (LPCTSTR)lpDevNames + lpDevNames->wOutputOffset,
+                                         lpDevMode);
+
+       ::GlobalUnlock(hDevNames);
+       if(hDevMode != NULL)
+               ::GlobalUnlock(hDevMode);
+       return hDC;
+}
+
+template <class T>
+class ATL_NO_VTABLE CPrintDialogImpl : public CCommonDialogImplBase
+{
+public:
+       // print dialog parameter block (note this is a reference)
+       PRINTDLG& m_pd;
+
+// Constructors
+       CPrintDialogImpl(BOOL bPrintSetupOnly = FALSE,  // TRUE for Print Setup, FALSE for Print Dialog
+                       DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
+                       HWND hWndParent = NULL)
+                       : m_pd(m_pdActual)
+       {
+               memset(&m_pdActual, 0, sizeof(m_pdActual));
+
+               m_pd.lStructSize = sizeof(m_pdActual);
+               m_pd.hwndOwner = hWndParent;
+               m_pd.Flags = (dwFlags | PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK);
+               m_pd.lpfnPrintHook = (LPPRINTHOOKPROC)T::HookProc;
+               m_pd.lpfnSetupHook = (LPSETUPHOOKPROC)T::HookProc;
+
+               if(bPrintSetupOnly)
+                       m_pd.Flags |= PD_PRINTSETUP;
+               else
+                       m_pd.Flags |= PD_RETURNDC;
+
+               m_pd.Flags &= ~PD_RETURNIC; // do not support information context
+       }
+
+// Operations
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               ATLASSERT((m_pd.Flags & PD_ENABLEPRINTHOOK) != 0);
+               ATLASSERT((m_pd.Flags & PD_ENABLESETUPHOOK) != 0);
+               ATLASSERT(m_pd.lpfnPrintHook != NULL);   // can still be a user hook
+               ATLASSERT(m_pd.lpfnSetupHook != NULL);   // can still be a user hook
+               ATLASSERT((m_pd.Flags & PD_RETURNDEFAULT) == 0);   // use GetDefaults for this
+
+               if(m_pd.hwndOwner == NULL)   // set only if not specified before
+                       m_pd.hwndOwner = hWndParent;
+
+               ATLASSERT(m_hWnd == NULL);
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
+
+               BOOL bRet = ::PrintDlg(&m_pd);
+
+               m_hWnd = NULL;
+
+               return bRet ? IDOK : IDCANCEL;
+       }
+
+       // GetDefaults will not display a dialog but will get device defaults
+       BOOL GetDefaults()
+       {
+               m_pd.Flags |= PD_RETURNDEFAULT;
+               ATLASSERT(m_pd.hDevMode == NULL);    // must be NULL
+               ATLASSERT(m_pd.hDevNames == NULL);   // must be NULL
+
+               return ::PrintDlg(&m_pd);
+       }
+
+       // Helpers for parsing information after successful return num. copies requested
+       int GetCopies() const
+       {
+               if((m_pd.Flags & PD_USEDEVMODECOPIES) != 0)
+               {
+                       LPDEVMODE lpDevMode = GetDevMode();
+                       return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
+               }
+
+               return m_pd.nCopies;
+       }
+
+       BOOL PrintCollate() const       // TRUE if collate checked
+       {
+               return ((m_pd.Flags & PD_COLLATE) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL PrintSelection() const     // TRUE if printing selection
+       {
+               return ((m_pd.Flags & PD_SELECTION) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL PrintAll() const           // TRUE if printing all pages
+       {
+               return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE;
+       }
+
+       BOOL PrintRange() const         // TRUE if printing page range
+       {
+               return ((m_pd.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL PrintToFile() const        // TRUE if printing to a file
+       {
+               return ((m_pd.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE;
+       }
+
+       int GetFromPage() const         // starting page if valid
+       {
+               return PrintRange() ? m_pd.nFromPage : -1;
+       }
+
+       int GetToPage() const           // ending page if valid
+       {
+               return PrintRange() ? m_pd.nToPage : -1;
+       }
+
+       LPDEVMODE GetDevMode() const    // return DEVMODE
+       {
+               if(m_pd.hDevMode == NULL)
+                       return NULL;
+
+               return (LPDEVMODE)::GlobalLock(m_pd.hDevMode);
+       }
+
+       LPCTSTR GetDriverName() const   // return driver name
+       {
+               if(m_pd.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
+               if(lpDev == NULL)
+                       return NULL;
+
+               return (LPCTSTR)lpDev + lpDev->wDriverOffset;
+       }
+
+       LPCTSTR GetDeviceName() const   // return device name
+       {
+               if(m_pd.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
+               if(lpDev == NULL)
+                       return NULL;
+
+               return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
+       }
+
+       LPCTSTR GetPortName() const     // return output port name
+       {
+               if(m_pd.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
+               if(lpDev == NULL)
+                       return NULL;
+
+               return (LPCTSTR)lpDev + lpDev->wOutputOffset;
+       }
+
+       HDC GetPrinterDC() const        // return HDC (caller must delete)
+       {
+               ATLASSERT((m_pd.Flags & PD_RETURNDC) != 0);
+               return m_pd.hDC;
+       }
+
+       // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
+       // This DC is returned, but also stored in m_pd.hDC as though it had been
+       // returned by CommDlg.  It is assumed that any previously obtained DC
+       // has been/will be deleted by the user.  This may be
+       // used without ever invoking the print/print setup dialogs.
+       HDC CreatePrinterDC()
+       {
+               m_pd.hDC = _AtlCreateDC(m_pd.hDevNames, m_pd.hDevMode);
+               return m_pd.hDC;
+       }
+
+// Implementation
+       PRINTDLG m_pdActual; // the Print/Print Setup need to share this
+
+       // The following handle the case of print setup... from the print dialog
+       CPrintDialogImpl(PRINTDLG& pdInit) : m_pd(pdInit)
+       { }
+
+       BEGIN_MSG_MAP(CPrintDialogImpl)
+#ifdef psh1
+               COMMAND_ID_HANDLER(psh1, OnPrintSetup) // print setup button when print is displayed
+#else // !psh1
+               COMMAND_ID_HANDLER(0x0400, OnPrintSetup) // value from dlgs.h
+#endif // !psh1
+       END_MSG_MAP()
+
+       LRESULT OnPrintSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/)
+       {
+               T dlgSetup(m_pd);
+               ModuleHelper::AddCreateWndData(&dlgSetup.m_thunk.cd, (CCommonDialogImplBase*)&dlgSetup);
+               return DefWindowProc(WM_COMMAND, MAKEWPARAM(wID, wNotifyCode), (LPARAM)hWndCtl);
+       }
+};
+
+class CPrintDialog : public CPrintDialogImpl<CPrintDialog>
+{
+public:
+       CPrintDialog(BOOL bPrintSetupOnly = FALSE,
+               DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
+               HWND hWndParent = NULL)
+               : CPrintDialogImpl<CPrintDialog>(bPrintSetupOnly, dwFlags, hWndParent)
+       { }
+
+       CPrintDialog(PRINTDLG& pdInit) : CPrintDialogImpl<CPrintDialog>(pdInit)
+       { }
+};
+
+#endif // _WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPrintDialogExImpl - new print dialog for Windows 2000
+
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+
+}; // namespace WTL
+
+#include <atlcom.h>
+
+extern "C" const __declspec(selectany) IID IID_IPrintDialogCallback = {0x5852a2c3, 0x6530, 0x11d1, {0xb6, 0xa3, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
+extern "C" const __declspec(selectany) IID IID_IPrintDialogServices = {0x509aaeda, 0x5639, 0x11d1, {0xb6, 0xa1, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
+
+namespace WTL
+{
+
+template <class T>
+class ATL_NO_VTABLE CPrintDialogExImpl : 
+                               public ATL::CWindow,
+                               public ATL::CMessageMap,
+                               public IPrintDialogCallback,
+                               public ATL::IObjectWithSiteImpl< T >
+{
+public:
+       PRINTDLGEX m_pdex;
+
+// Constructor
+       CPrintDialogExImpl(DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
+                               HWND hWndParent = NULL)
+       {
+               memset(&m_pdex, 0, sizeof(m_pdex));
+
+               m_pdex.lStructSize = sizeof(PRINTDLGEX);
+               m_pdex.hwndOwner = hWndParent;
+               m_pdex.Flags = dwFlags;
+               m_pdex.nStartPage = START_PAGE_GENERAL;
+               // callback object will be set in DoModal
+
+               m_pdex.Flags &= ~PD_RETURNIC; // do not support information context
+       }
+
+// Operations
+       HRESULT DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               ATLASSERT(m_hWnd == NULL);
+               ATLASSERT((m_pdex.Flags & PD_RETURNDEFAULT) == 0);   // use GetDefaults for this
+
+               if(m_pdex.hwndOwner == NULL)   // set only if not specified before
+                       m_pdex.hwndOwner = hWndParent;
+
+               T* pT = static_cast<T*>(this);
+               m_pdex.lpCallback = (IUnknown*)(IPrintDialogCallback*)pT;
+
+               HRESULT hResult = ::PrintDlgEx(&m_pdex);
+
+               m_hWnd = NULL;
+
+               return hResult;
+       }
+
+       BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
+               return TRUE;
+       }
+
+       // GetDefaults will not display a dialog but will get device defaults
+       HRESULT GetDefaults()
+       {
+               m_pdex.Flags |= PD_RETURNDEFAULT;
+               ATLASSERT(m_pdex.hDevMode == NULL);    // must be NULL
+               ATLASSERT(m_pdex.hDevNames == NULL);   // must be NULL
+
+               return ::PrintDlgEx(&m_pdex);
+       }
+
+       // Helpers for parsing information after successful return num. copies requested
+       int GetCopies() const
+       {
+               if((m_pdex.Flags & PD_USEDEVMODECOPIES) != 0)
+               {
+                       LPDEVMODE lpDevMode = GetDevMode();
+                       return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
+               }
+
+               return m_pdex.nCopies;
+       }
+
+       BOOL PrintCollate() const       // TRUE if collate checked
+       {
+               return ((m_pdex.Flags & PD_COLLATE) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL PrintSelection() const     // TRUE if printing selection
+       {
+               return ((m_pdex.Flags & PD_SELECTION) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL PrintAll() const           // TRUE if printing all pages
+       {
+               return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE;
+       }
+
+       BOOL PrintRange() const         // TRUE if printing page range
+       {
+               return ((m_pdex.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL PrintToFile() const        // TRUE if printing to a file
+       {
+               return ((m_pdex.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE;
+       }
+
+       LPDEVMODE GetDevMode() const    // return DEVMODE
+       {
+               if(m_pdex.hDevMode == NULL)
+                       return NULL;
+
+               return (LPDEVMODE)::GlobalLock(m_pdex.hDevMode);
+       }
+
+       LPCTSTR GetDriverName() const   // return driver name
+       {
+               if(m_pdex.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
+               if(lpDev == NULL)
+                       return NULL;
+
+               return (LPCTSTR)lpDev + lpDev->wDriverOffset;
+       }
+
+       LPCTSTR GetDeviceName() const   // return device name
+       {
+               if(m_pdex.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
+               if(lpDev == NULL)
+                       return NULL;
+
+               return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
+       }
+
+       LPCTSTR GetPortName() const     // return output port name
+       {
+               if(m_pdex.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
+               if(lpDev == NULL)
+                       return NULL;
+
+               return (LPCTSTR)lpDev + lpDev->wOutputOffset;
+       }
+
+       HDC GetPrinterDC() const        // return HDC (caller must delete)
+       {
+               ATLASSERT((m_pdex.Flags & PD_RETURNDC) != 0);
+               return m_pdex.hDC;
+       }
+
+       // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
+       // This DC is returned, but also stored in m_pdex.hDC as though it had been
+       // returned by CommDlg.  It is assumed that any previously obtained DC
+       // has been/will be deleted by the user.  This may be
+       // used without ever invoking the print/print setup dialogs.
+       HDC CreatePrinterDC()
+       {
+               m_pdex.hDC = _AtlCreateDC(m_pdex.hDevNames, m_pdex.hDevMode);
+               return m_pdex.hDC;
+       }
+
+// Implementation - interfaces
+
+// IUnknown
+       STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
+       {
+               if(ppvObject == NULL)
+                       return E_POINTER;
+
+               T* pT = static_cast<T*>(this);
+               if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IPrintDialogCallback))
+               {
+                       *ppvObject = (IPrintDialogCallback*)pT;
+                       // AddRef() not needed
+                       return S_OK;
+               }
+               else if(IsEqualGUID(riid, IID_IObjectWithSite))
+               {
+                       *ppvObject = (IObjectWithSite*)pT;
+                       // AddRef() not needed
+                       return S_OK;
+               }
+
+               return E_NOINTERFACE;
+       }
+
+       virtual ULONG STDMETHODCALLTYPE AddRef()
+       {
+               return 1;
+       }
+
+       virtual ULONG STDMETHODCALLTYPE Release()
+       {
+               return 1;
+       }
+
+// IPrintDialogCallback
+       STDMETHOD(InitDone)()
+       {
+               return S_FALSE;
+       }
+
+       STDMETHOD(SelectionChange)()
+       {
+               return S_FALSE;
+       }
+
+       STDMETHOD(HandleMessage)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
+       {
+               // set up m_hWnd the first time
+               if(m_hWnd == NULL)
+                       Attach(hWnd);
+
+               // call message map
+               HRESULT hRet = ProcessWindowMessage(hWnd, uMsg, wParam, lParam, *plResult, 0) ? S_OK : S_FALSE;
+               if(hRet == S_OK && uMsg == WM_NOTIFY)   // return in DWLP_MSGRESULT
+                       ::SetWindowLongPtr(GetParent(), DWLP_MSGRESULT, (LONG_PTR)*plResult);
+
+               if(uMsg == WM_INITDIALOG && hRet == S_OK && (BOOL)*plResult != FALSE)
+                       hRet = S_FALSE;
+
+               return hRet;
+       }
+};
+
+class CPrintDialogEx : public CPrintDialogExImpl<CPrintDialogEx>
+{
+public:
+       CPrintDialogEx(
+               DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
+               HWND hWndParent = NULL)
+               : CPrintDialogExImpl<CPrintDialogEx>(dwFlags, hWndParent)
+       { }
+
+       DECLARE_EMPTY_MSG_MAP()
+};
+
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPageSetupDialogImpl - Page Setup dialog
+
+#ifndef _WIN32_WCE
+
+template <class T>
+class ATL_NO_VTABLE CPageSetupDialogImpl : public CCommonDialogImplBase
+{
+public:
+       PAGESETUPDLG m_psd;
+       ATL::CWndProcThunk m_thunkPaint;
+
+// Constructors
+       CPageSetupDialogImpl(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
+       {
+               memset(&m_psd, 0, sizeof(m_psd));
+
+               m_psd.lStructSize = sizeof(m_psd);
+               m_psd.hwndOwner = hWndParent;
+               m_psd.Flags = (dwFlags | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK);
+               m_psd.lpfnPageSetupHook = (LPPAGESETUPHOOK)T::HookProc;
+               m_thunkPaint.Init((WNDPROC)T::PaintHookProc, this);
+#if (_ATL_VER >= 0x0700)
+               m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)m_thunkPaint.GetWNDPROC();
+#else
+               m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)&(m_thunkPaint.thunk);
+#endif
+       }
+
+       DECLARE_EMPTY_MSG_MAP()
+
+// Attributes
+       LPDEVMODE GetDevMode() const    // return DEVMODE
+       {
+               if(m_psd.hDevMode == NULL)
+                       return NULL;
+
+               return (LPDEVMODE)::GlobalLock(m_psd.hDevMode);
+       }
+
+       LPCTSTR GetDriverName() const   // return driver name
+       {
+               if(m_psd.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
+               return (LPCTSTR)lpDev + lpDev->wDriverOffset;
+       }
+
+       LPCTSTR GetDeviceName() const   // return device name
+       {
+               if(m_psd.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
+               return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
+       }
+
+       LPCTSTR GetPortName() const     // return output port name
+       {
+               if(m_psd.hDevNames == NULL)
+                       return NULL;
+
+               LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
+               return (LPCTSTR)lpDev + lpDev->wOutputOffset;
+       }
+
+       HDC CreatePrinterDC()
+       {
+               return _AtlCreateDC(m_psd.hDevNames, m_psd.hDevMode);
+       }
+
+       SIZE GetPaperSize() const
+       {
+               SIZE size;
+               size.cx = m_psd.ptPaperSize.x;
+               size.cy = m_psd.ptPaperSize.y;
+               return size;
+       }
+
+       void GetMargins(LPRECT lpRectMargins, LPRECT lpRectMinMargins) const
+       {
+               if(lpRectMargins != NULL)
+                       *lpRectMargins = m_psd.rtMargin;
+               if(lpRectMinMargins != NULL)
+                       *lpRectMinMargins = m_psd.rtMinMargin;
+       }
+
+// Operations
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               ATLASSERT((m_psd.Flags & PSD_ENABLEPAGESETUPHOOK) != 0);
+               ATLASSERT((m_psd.Flags & PSD_ENABLEPAGEPAINTHOOK) != 0);
+               ATLASSERT(m_psd.lpfnPageSetupHook != NULL);   // can still be a user hook
+               ATLASSERT(m_psd.lpfnPagePaintHook != NULL);   // can still be a user hook
+
+               if(m_psd.hwndOwner == NULL)   // set only if not specified before
+                       m_psd.hwndOwner = hWndParent;
+
+               ATLASSERT(m_hWnd == NULL);
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
+
+               BOOL bRet = ::PageSetupDlg(&m_psd);
+
+               m_hWnd = NULL;
+
+               return bRet ? IDOK : IDCANCEL;
+       }
+
+// Implementation
+       static UINT_PTR CALLBACK PaintHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               T* pT = (T*)hWnd;
+               UINT_PTR uRet = 0;
+               switch(uMsg)
+               {
+               case WM_PSD_PAGESETUPDLG:
+                       uRet = pT->PreDrawPage(LOWORD(wParam), HIWORD(wParam), (LPPAGESETUPDLG)lParam);
+                       break;
+               case WM_PSD_FULLPAGERECT:
+               case WM_PSD_MINMARGINRECT:
+               case WM_PSD_MARGINRECT:
+               case WM_PSD_GREEKTEXTRECT:
+               case WM_PSD_ENVSTAMPRECT:
+               case WM_PSD_YAFULLPAGERECT:
+                       uRet = pT->OnDrawPage(uMsg, (HDC)wParam, (LPRECT)lParam);
+                       break;
+               default:
+                       ATLTRACE2(atlTraceUI, 0, _T("CPageSetupDialogImpl::PaintHookProc - unknown message received\n"));
+                       break;
+               }
+               return uRet;
+       }
+
+// Overridables
+       UINT_PTR PreDrawPage(WORD /*wPaper*/, WORD /*wFlags*/, LPPAGESETUPDLG /*pPSD*/)
+       {
+               // return 1 to prevent any more drawing
+               return 0;
+       }
+
+       UINT_PTR OnDrawPage(UINT /*uMsg*/, HDC /*hDC*/, LPRECT /*lpRect*/)
+       {
+               return 0; // do the default
+       }
+};
+
+class CPageSetupDialog : public CPageSetupDialogImpl<CPageSetupDialog>
+{
+public:
+       CPageSetupDialog(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
+               : CPageSetupDialogImpl<CPageSetupDialog>(dwFlags, hWndParent)
+       { }
+
+       // override PaintHookProc and references to handlers
+       static UINT_PTR CALLBACK PaintHookProc(HWND, UINT, WPARAM, LPARAM)
+       {
+               return 0;
+       }
+};
+
+#endif // _WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CFindReplaceDialogImpl - Find/FindReplace modeless dialogs
+
+#ifndef _WIN32_WCE
+
+template <class T>
+class ATL_NO_VTABLE CFindReplaceDialogImpl : public CCommonDialogImplBase
+{
+public:
+       enum { _cchFindReplaceBuffer = 128 };
+
+       FINDREPLACE m_fr;
+       TCHAR m_szFindWhat[_cchFindReplaceBuffer];
+       TCHAR m_szReplaceWith[_cchFindReplaceBuffer];
+
+// Constructors
+       CFindReplaceDialogImpl()
+       {
+               memset(&m_fr, 0, sizeof(m_fr));
+               m_szFindWhat[0] = _T('\0');
+               m_szReplaceWith[0] = _T('\0');
+
+               m_fr.lStructSize = sizeof(m_fr);
+               m_fr.Flags = FR_ENABLEHOOK;
+               m_fr.lpfnHook = (LPFRHOOKPROC)T::HookProc;
+               m_fr.lpstrFindWhat = (LPTSTR)m_szFindWhat;
+               m_fr.wFindWhatLen = _cchFindReplaceBuffer;
+               m_fr.lpstrReplaceWith = (LPTSTR)m_szReplaceWith;
+               m_fr.wReplaceWithLen = _cchFindReplaceBuffer;
+       }
+
+       // Note: You must allocate the object on the heap.
+       //       If you do not, you must override OnFinalMessage()
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+
+       HWND Create(BOOL bFindDialogOnly, // TRUE for Find, FALSE for FindReplace
+                       LPCTSTR lpszFindWhat,
+                       LPCTSTR lpszReplaceWith = NULL,
+                       DWORD dwFlags = FR_DOWN,
+                       HWND hWndParent = NULL)
+       {
+               ATLASSERT((m_fr.Flags & FR_ENABLEHOOK) != 0);
+               ATLASSERT(m_fr.lpfnHook != NULL);
+
+               m_fr.Flags |= dwFlags;
+
+               if(hWndParent == NULL)
+                       m_fr.hwndOwner = ::GetActiveWindow();
+               else
+                       m_fr.hwndOwner = hWndParent;
+               ATLASSERT(m_fr.hwndOwner != NULL); // must have an owner for modeless dialog
+
+               if(lpszFindWhat != NULL)
+                       SecureHelper::strncpy_x(m_szFindWhat, _countof(m_szFindWhat), lpszFindWhat, _TRUNCATE);
+
+               if(lpszReplaceWith != NULL)
+                       SecureHelper::strncpy_x(m_szReplaceWith, _countof(m_szReplaceWith), lpszReplaceWith, _TRUNCATE);
+
+               ATLASSERT(m_hWnd == NULL);
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
+
+               HWND hWnd = NULL;
+               if(bFindDialogOnly)
+                       hWnd = ::FindText(&m_fr);
+               else
+                       hWnd = ::ReplaceText(&m_fr);
+
+               ATLASSERT(m_hWnd == hWnd);
+               return hWnd;
+       }
+
+       static const UINT GetFindReplaceMsg()
+       {
+               static const UINT nMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING);
+               return nMsgFindReplace;
+       }
+       // call while handling FINDMSGSTRING registered message
+       // to retreive the object
+       static T* PASCAL GetNotifier(LPARAM lParam)
+       {
+               ATLASSERT(lParam != NULL);
+               T* pDlg = (T*)(lParam - offsetof(T, m_fr));
+               return pDlg;
+       }
+
+// Operations
+       // Helpers for parsing information after successful return
+       LPCTSTR GetFindString() const    // get find string
+       {
+               return (LPCTSTR)m_fr.lpstrFindWhat;
+       }
+
+       LPCTSTR GetReplaceString() const // get replacement string
+       {
+               return (LPCTSTR)m_fr.lpstrReplaceWith;
+       }
+
+       BOOL SearchDown() const          // TRUE if search down, FALSE is up
+       {
+               return ((m_fr.Flags & FR_DOWN) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL FindNext() const            // TRUE if command is find next
+       {
+               return ((m_fr.Flags & FR_FINDNEXT) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL MatchCase() const           // TRUE if matching case
+       {
+               return ((m_fr.Flags & FR_MATCHCASE) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL MatchWholeWord() const      // TRUE if matching whole words only
+       {
+               return ((m_fr.Flags & FR_WHOLEWORD) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL ReplaceCurrent() const      // TRUE if replacing current string
+       {
+               return ((m_fr. Flags & FR_REPLACE) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL ReplaceAll() const          // TRUE if replacing all occurrences
+       {
+               return ((m_fr.Flags & FR_REPLACEALL) != 0) ? TRUE : FALSE;
+       }
+
+       BOOL IsTerminating() const       // TRUE if terminating dialog
+       {
+               return ((m_fr.Flags & FR_DIALOGTERM) != 0) ? TRUE : FALSE ;
+       }
+};
+
+class CFindReplaceDialog : public CFindReplaceDialogImpl<CFindReplaceDialog>
+{
+public:
+       DECLARE_EMPTY_MSG_MAP()
+};
+
+#endif // !_WIN32_WCE
+
+
+/////////////////////////////////////////////////////////////////////////
+// CDialogBaseUnits - Dialog Units helper
+//
+
+class CDialogBaseUnits
+{
+public:
+       SIZE m_sizeUnits;
+
+// Constructors
+       CDialogBaseUnits()
+       {
+               // The base units of the out-dated System Font
+               LONG nDlgBaseUnits = ::GetDialogBaseUnits();
+               m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
+               m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
+       }
+
+       CDialogBaseUnits(HWND hWnd)
+       {
+               if(!InitDialogBaseUnits(hWnd)) {
+                       LONG nDlgBaseUnits = ::GetDialogBaseUnits();
+                       m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
+                       m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
+               }
+       }
+
+       CDialogBaseUnits(HFONT hFont, HWND hWnd = NULL)
+       {
+               if(!InitDialogBaseUnits(hFont, hWnd)) {
+                       LONG nDlgBaseUnits = ::GetDialogBaseUnits();
+                       m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
+                       m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
+               }
+       }
+
+       CDialogBaseUnits(LOGFONT lf, HWND hWnd = NULL)
+       {
+               if(!InitDialogBaseUnits(lf, hWnd)) {
+                       LONG nDlgBaseUnits = ::GetDialogBaseUnits();
+                       m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
+                       m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
+               }
+       }
+
+// Operations
+       BOOL InitDialogBaseUnits(HWND hWnd)
+       {
+               ATLASSERT(::IsWindow(hWnd));
+               RECT rc = { 0, 0, 4, 8 };
+               if(!::MapDialogRect(hWnd, &rc)) return FALSE;
+               m_sizeUnits.cx = rc.right;
+               m_sizeUnits.cy = rc.bottom;
+               return TRUE;
+       }
+
+       BOOL InitDialogBaseUnits(LOGFONT lf, HWND hWnd = NULL)
+       {
+               CFont font;
+               font.CreateFontIndirect(&lf);
+               if(font.IsNull()) return FALSE;
+               return InitDialogBaseUnits(font, hWnd);
+       }
+
+       BOOL InitDialogBaseUnits(HFONT hFont, HWND hWnd = NULL)
+       {
+               ATLASSERT(hFont != NULL);
+               CWindowDC dc = hWnd;
+               TEXTMETRIC tmText = { 0 };
+               SIZE sizeText = { 0 };
+               HFONT hFontOld = dc.SelectFont(hFont);
+               dc.GetTextMetrics(&tmText);
+               m_sizeUnits.cy = tmText.tmHeight + tmText.tmExternalLeading;
+               dc.GetTextExtent(_T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, &sizeText);
+               m_sizeUnits.cx = (sizeText.cx + 26) / 52;
+               dc.SelectFont(hFontOld);
+               return TRUE;
+       }
+
+       SIZE GetDialogBaseUnits() const
+       {
+               return m_sizeUnits;
+       }
+
+       INT MapDialogPixelsX(INT x) const
+       {
+               return ::MulDiv(x, 4, m_sizeUnits.cx);  // Pixels X to DLU
+       }
+
+       INT MapDialogPixelsY(INT y) const
+       {
+               return ::MulDiv(y, 8, m_sizeUnits.cy);  // Pixels Y to DLU
+       }
+
+       POINT MapDialogPixels(POINT pt) const
+       {
+               POINT out = { MapDialogPixelsX(pt.x), MapDialogPixelsY(pt.y) };
+               return out;
+       }
+
+       SIZE MapDialogPixels(SIZE input) const
+       {
+               SIZE out = { MapDialogPixelsX(input.cx), MapDialogPixelsY(input.cy) };
+               return out;
+       }
+
+       RECT MapDialogPixels(RECT input) const
+       {
+               RECT out = { MapDialogPixelsX(input.left), MapDialogPixelsY(input.top), MapDialogPixelsX(input.right), MapDialogPixelsY(input.bottom) };
+               return out;
+       }
+
+       INT MapDialogUnitsX(INT x) const
+       {
+               return ::MulDiv(x, m_sizeUnits.cx, 4);  // DLU to Pixels X
+       }
+
+       INT MapDialogUnitsY(INT y) const
+       {
+               return ::MulDiv(y, m_sizeUnits.cx, 8);  // DLU to Pixels Y
+       }
+
+       POINT MapDialogUnits(POINT pt) const
+       {
+               POINT out = { MapDialogUnitsX(pt.x), MapDialogUnitsY(pt.y) };
+               return out;
+       }
+
+       SIZE MapDialogUnits(SIZE input) const
+       {
+               SIZE out = { MapDialogUnitsX(input.cx), MapDialogUnitsY(input.cy) };
+               return out;
+       }
+
+       RECT MapDialogUnits(RECT input) const
+       {
+               RECT out = { MapDialogUnitsX(input.left), MapDialogUnitsY(input.top), MapDialogUnitsX(input.right), MapDialogUnitsY(input.bottom) };
+               return out;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMemDlgTemplate - in-memory dialog template - DLGTEMPLATE or DLGTEMPLATEEX
+
+#if (_ATL_VER >= 0x800)
+typedef ATL::_DialogSplitHelper::DLGTEMPLATEEX DLGTEMPLATEEX;
+typedef ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX DLGITEMTEMPLATEEX;
+#else // (_ATL_VER >= 0x800)
+typedef ATL::_DialogSizeHelper::_ATL_DLGTEMPLATEEX DLGTEMPLATEEX;
+#pragma pack(push, 4)
+struct DLGITEMTEMPLATEEX
+{
+       DWORD helpID;
+       DWORD exStyle;
+       DWORD style;
+       short x;
+       short y;
+       short cx;
+       short cy;
+       DWORD id;
+};
+#pragma pack(pop)
+#endif // (_ATL_VER >= 0x800)
+
+
+class CMemDlgTemplate
+{
+public:
+       enum StdCtrlType
+       {
+               CTRL_BUTTON    = 0x0080,
+               CTRL_EDIT      = 0x0081,
+               CTRL_STATIC    = 0x0082,
+               CTRL_LISTBOX   = 0x0083,
+               CTRL_SCROLLBAR = 0x0084,
+               CTRL_COMBOBOX  = 0x0085
+       };
+
+       CMemDlgTemplate() : m_hData(NULL), m_pData(NULL), m_pPtr(NULL), m_cAllocated(0)
+       { }
+
+       ~CMemDlgTemplate()
+       {
+               Reset();
+       }
+
+       bool IsValid() const
+       {
+               return (m_pData != NULL);
+       }
+
+       bool IsTemplateEx() const
+       {
+               return (IsValid() && ((DLGTEMPLATEEX*)m_pData)->signature == 0xFFFF);
+       }
+
+       LPDLGTEMPLATE GetTemplatePtr()
+       {
+               return reinterpret_cast<LPDLGTEMPLATE>(m_pData);
+       }
+
+       DLGTEMPLATEEX* GetTemplateExPtr()
+       {
+               return reinterpret_cast<DLGTEMPLATEEX*>(m_pData);
+       }
+
+       void Reset()
+       {
+               if (IsValid()) {
+#ifndef UNDER_CE
+                       ::GlobalUnlock(m_pData);
+#endif
+                       ATLVERIFY(::GlobalFree(m_hData) == NULL);
+               }
+
+               m_hData = NULL;
+               m_pData = NULL;
+               m_pPtr = NULL;
+               m_cAllocated = 0;
+       }
+
+       void Create(bool bDlgEx, LPCTSTR lpszCaption, RECT rc, DWORD dwStyle = 0, DWORD dwExStyle = 0,
+               LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0,
+               ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U)
+       {
+               Create(bDlgEx, lpszCaption, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle,
+                       lpstrFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName.m_lpstr, Menu.m_lpstr);
+       }
+
+       void Create(bool bDlgEx, LPCTSTR lpszCaption, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle = 0, DWORD dwExStyle = 0,
+               LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0,
+               ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U)
+       {
+               // Should have DS_SETFONT style to set the dialog font name and size
+               if (lpstrFontName != NULL)
+               {
+                       dwStyle |= DS_SETFONT;
+               }
+               else
+               {
+                       dwStyle &= ~DS_SETFONT;
+               }
+
+               if (bDlgEx)
+               {
+                       DLGTEMPLATEEX dlg = {1, 0xFFFF, dwHelpID, dwExStyle, dwStyle, 0, nX, nY, nWidth, nHeight};
+                       AddData(&dlg, sizeof(dlg));
+               }
+               else
+               {
+                       DLGTEMPLATE dlg = {dwStyle, dwExStyle, 0, nX, nY, nWidth, nHeight};
+                       AddData(&dlg, sizeof(dlg));
+               }
+
+#ifndef _WIN32_WCE
+               if (Menu.m_lpstr == NULL)
+               {
+                       WORD menuData = 0;
+                       AddData(&menuData, sizeof(WORD));
+               }
+               else if (IS_INTRESOURCE(Menu.m_lpstr))
+               {
+                       WORD menuData[] = {0xFFFF, (WORD)Menu.m_lpstr};
+                       AddData(menuData, sizeof(menuData));
+               }
+               else
+               {
+                       AddString(Menu.m_lpstr);
+               }
+#else // _WIN32_WCE
+               // Windows CE doesn't support the addition of menus to a dialog box
+               ATLASSERT(Menu.m_lpstr == NULL);
+               Menu.m_lpstr;   // avoid level 4 warning
+               WORD menuData = 0;
+               AddData(&menuData, sizeof(WORD));
+#endif // _WIN32_WCE
+
+               if (ClassName.m_lpstr == NULL)
+               {
+                       WORD classData = 0;
+                       AddData(&classData, sizeof(WORD));
+               }
+               else if (IS_INTRESOURCE(ClassName.m_lpstr))
+               {
+                       WORD classData[] = {0xFFFF, (WORD)ClassName.m_lpstr};
+                       AddData(classData, sizeof(classData));
+               }
+               else
+               {
+                       AddString(ClassName.m_lpstr);
+               }
+
+               // Set dialog caption
+               AddString(lpszCaption);
+
+               if (lpstrFontName != NULL)
+               {
+                       AddData(&wFontSize, sizeof(wFontSize));
+
+                       if (bDlgEx)
+                       {
+                               AddData(&wWeight, sizeof(wWeight));
+                               AddData(&bItalic, sizeof(bItalic));
+                               AddData(&bCharset, sizeof(bCharset));
+                       }
+
+                       AddString(lpstrFontName);
+               }
+       }
+
+       void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, RECT rc, DWORD dwStyle, DWORD dwExStyle,
+                       ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
+       {
+               AddControl(ClassName.m_lpstr, wId, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle,
+                       Text.m_lpstr, pCreationData, nCreationData, dwHelpID);
+       }
+
+       void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle, DWORD dwExStyle,
+                       ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
+       {
+               ATLASSERT(IsValid());
+
+               // DWORD align data
+               m_pPtr = (LPBYTE)(DWORD_PTR)((DWORD)(DWORD_PTR)(m_pPtr + 3) & (~3));
+
+               if (IsTemplateEx())
+               {
+                       DLGTEMPLATEEX* dlg = (DLGTEMPLATEEX*)m_pData;
+                       dlg->cDlgItems++;
+
+                       DLGITEMTEMPLATEEX item = {dwHelpID, ATL::CControlWinTraits::GetWndExStyle(0) | dwExStyle, ATL::CControlWinTraits::GetWndStyle(0) | dwStyle, nX, nY, nWidth, nHeight, wId};
+                       AddData(&item, sizeof(item));
+               }
+               else
+               {
+                       LPDLGTEMPLATE dlg = (LPDLGTEMPLATE)m_pData;
+                       dlg->cdit++;
+
+                       DLGITEMTEMPLATE item = {ATL::CControlWinTraits::GetWndStyle(0) | dwStyle, ATL::CControlWinTraits::GetWndExStyle(0) | dwExStyle, nX, nY, nWidth, nHeight, wId};
+                       AddData(&item, sizeof(item));
+               }
+
+               ATLASSERT(ClassName.m_lpstr != NULL);
+               if (IS_INTRESOURCE(ClassName.m_lpstr))
+               {
+                       WORD wData[] = {0xFFFF, (WORD)ClassName.m_lpstr};
+                       AddData(wData, sizeof(wData));
+               }
+               else
+               {
+                       AddString(ClassName.m_lpstr);
+               }
+
+               if (Text.m_lpstr == NULL)
+               {
+                       WORD classData = 0;
+                       AddData(&classData, sizeof(WORD));
+               }
+               else if (IS_INTRESOURCE(Text.m_lpstr))
+               {
+                       WORD wData[] = {0xFFFF, (WORD)Text.m_lpstr};
+                       AddData(wData, sizeof(wData));
+               }
+               else
+               {
+                       AddString(Text.m_lpstr);
+               }
+
+               AddData(&nCreationData, sizeof(nCreationData));
+
+               if ((nCreationData != 0))
+               {
+                       ATLASSERT(pCreationData != NULL);
+                       AddData(pCreationData, nCreationData * sizeof(WORD));
+               }
+       }
+
+       void AddStdControl(StdCtrlType CtrlType, WORD wId, short nX, short nY, short nWidth, short nHeight,
+                          DWORD dwStyle, DWORD dwExStyle, ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
+       {
+               AddControl(CtrlType, wId, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, Text, pCreationData, nCreationData, dwHelpID);
+       }
+
+       void AddData(LPCVOID pData, size_t nData)
+       {
+               ATLASSERT(pData != NULL);
+
+               const SIZE_T ALLOCATION_INCREMENT = 1024;
+
+               if (m_pData == NULL)
+               {
+                       m_cAllocated = ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT;
+                       m_hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, m_cAllocated);
+                       ATLASSERT(m_hData != NULL);
+#ifndef UNDER_CE
+                       m_pPtr = m_pData = static_cast<LPBYTE>(::GlobalLock(m_hData));
+#else
+                       m_pPtr = m_pData = static_cast<LPBYTE>(m_hData);
+#endif
+                       ATLASSERT(m_pData != NULL);
+               }
+               else if (((m_pPtr - m_pData) + nData) > m_cAllocated)
+               {
+                       SIZE_T ptrPos = (m_pPtr - m_pData);
+                       m_cAllocated += ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT;
+#ifndef UNDER_CE
+                       ::GlobalUnlock(m_pData);
+#endif
+                       m_hData = ::GlobalReAlloc(m_hData, m_cAllocated, GMEM_MOVEABLE | GMEM_ZEROINIT);
+                       ATLASSERT(m_hData != NULL);
+#ifndef UNDER_CE
+                       m_pData = static_cast<LPBYTE>(::GlobalLock(m_hData));
+#else
+                       m_pData = static_cast<LPBYTE>(m_hData);
+#endif
+                       ATLASSERT(m_pData != NULL);
+                       m_pPtr = m_pData + ptrPos;
+               }
+
+               SecureHelper::memcpy_x(m_pPtr, m_cAllocated - (m_pPtr - m_pData), pData, nData);
+
+               m_pPtr += nData;
+       }
+
+       void AddString(LPCTSTR lpszStr)
+       {
+               if (lpszStr == NULL)
+               {
+                       WCHAR szEmpty = 0;
+                       AddData(&szEmpty, sizeof(szEmpty));
+               }
+               else
+               {
+                       USES_CONVERSION;
+                       LPCWSTR lpstr = T2CW(lpszStr);
+                       int nSize = lstrlenW(lpstr) + 1;
+                       AddData(lpstr, nSize * sizeof(WCHAR));
+               }
+       }
+
+       HANDLE m_hData;
+       LPBYTE m_pData;
+       LPBYTE m_pPtr;
+       SIZE_T m_cAllocated;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Dialog and control macros for indirect dialogs
+
+// for DLGTEMPLATE
+#define BEGIN_DIALOG(x, y, width, height) \
+       void DoInitTemplate() \
+       { \
+               bool bExTemplate = false; \
+               short nX = x, nY = y, nWidth = width, nHeight = height; \
+               LPCTSTR szCaption = NULL; \
+               DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \
+               DWORD dwExStyle = 0; \
+               LPCTSTR szFontName = NULL; \
+               WORD wFontSize = 0; \
+               WORD wWeight = 0; \
+               BYTE bItalic = 0; \
+               BYTE bCharset = 0; \
+               DWORD dwHelpID = 0; \
+               ATL::_U_STRINGorID Menu = 0U; \
+               ATL::_U_STRINGorID ClassName = 0U;
+
+// for DLGTEMPLATEEX
+#define BEGIN_DIALOG_EX(x, y, width, height, helpID) \
+       void DoInitTemplate() \
+       { \
+               bool bExTemplate = true; \
+               short nX = x, nY = y, nWidth = width, nHeight = height; \
+               LPCTSTR szCaption = NULL; \
+               DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \
+               DWORD dwExStyle = 0; \
+               LPCTSTR szFontName = NULL; \
+               WORD wFontSize = 0; \
+               WORD wWeight = 0; \
+               BYTE bItalic = 0; \
+               BYTE bCharset = 0; \
+               DWORD dwHelpID = helpID; \
+               ATL::_U_STRINGorID Menu = 0U; \
+               ATL::_U_STRINGorID ClassName = 0U;
+
+#define END_DIALOG() \
+               m_Template.Create(bExTemplate, szCaption, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, szFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName, Menu); \
+       };
+
+#define DIALOG_CAPTION(caption) \
+               szCaption = caption;
+#define DIALOG_STYLE(style) \
+               dwStyle = style;
+#define DIALOG_EXSTYLE(exStyle) \
+               dwExStyle = exStyle;
+#define DIALOG_FONT(pointSize, typeFace) \
+               wFontSize = pointSize; \
+               szFontName = typeFace;
+#define DIALOG_FONT_EX(pointsize, typeface, weight, italic, charset) \
+               ATLASSERT(bExTemplate); \
+               wFontSize = pointsize; \
+               szFontName = typeface; \
+               wWeight = weight; \
+               bItalic = italic; \
+               bCharset = charset;
+#define DIALOG_MENU(menuName) \
+               Menu = menuName;
+#define DIALOG_CLASS(className) \
+               ClassName = className;
+
+#define BEGIN_CONTROLS_MAP() \
+       void DoInitControls() \
+       {
+
+#define END_CONTROLS_MAP() \
+       };
+
+
+#define CONTROL_LTEXT(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_LEFT | WS_GROUP, exStyle, text, NULL, 0);
+#define CONTROL_CTEXT(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_CENTER | WS_GROUP, exStyle, text, NULL, 0);
+#define CONTROL_RTEXT(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_RIGHT | WS_GROUP, exStyle, text, NULL, 0);
+#define CONTROL_PUSHBUTTON(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
+#define CONTROL_DEFPUSHBUTTON(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_DEFPUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
+#ifndef _WIN32_WCE
+#define CONTROL_PUSHBOX(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBOX | WS_TABSTOP, exStyle, text, NULL, 0);
+#endif // !_WIN32_WCE
+#define CONTROL_STATE3(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_3STATE | WS_TABSTOP, exStyle, text, NULL, 0);
+#define CONTROL_AUTO3STATE(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTO3STATE | WS_TABSTOP, exStyle, text, NULL, 0);
+#define CONTROL_CHECKBOX(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_CHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0);
+#define CONTROL_AUTOCHECKBOX(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTOCHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0);
+#define CONTROL_RADIOBUTTON(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_RADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
+#define CONTROL_AUTORADIOBUTTON(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTORADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
+#define CONTROL_COMBOBOX(id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_COMBOBOX, (WORD)id, x, y, width, height, style | CBS_DROPDOWN | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0);
+#define CONTROL_EDITTEXT(id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_EDIT, (WORD)id, x, y, width, height, style | ES_LEFT | WS_BORDER | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0);
+#define CONTROL_GROUPBOX(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_GROUPBOX, exStyle, text, NULL, 0);
+#define CONTROL_LISTBOX(id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_LISTBOX, (WORD)id, x, y, width, height, style | LBS_NOTIFY | WS_BORDER, exStyle, (LPCTSTR)NULL, NULL, 0);
+#define CONTROL_SCROLLBAR(id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_SCROLLBAR, (WORD)id, x, y, width, height, style | SBS_HORZ, exStyle, (LPCTSTR)NULL, NULL, 0);
+#define CONTROL_ICON(text, id, x, y, width, height, style, exStyle) \
+       m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_ICON, exStyle, text, NULL, 0);
+#define CONTROL_CONTROL(text, id, className, style, x, y, width, height, exStyle) \
+       m_Template.AddControl(className, (WORD)id, x, y, width, height, style, exStyle, text, NULL, 0);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CIndirectDialogImpl - dialogs with template in memory
+
+template <class T, class TDlgTemplate = CMemDlgTemplate, class TBase = ATL::CDialogImpl<T, ATL::CWindow> >
+class ATL_NO_VTABLE CIndirectDialogImpl : public TBase
+{
+public:
+       enum { IDD = 0 };   // no dialog template resource
+
+       TDlgTemplate m_Template;
+
+       void CreateTemplate()
+       {
+               T* pT = static_cast<T*>(this);
+               pT->DoInitTemplate();
+               pT->DoInitControls();
+       }
+
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_hWnd == NULL);
+
+               if (!m_Template.IsValid())
+                       CreateTemplate();
+
+#if (_ATL_VER >= 0x0800)
+               // Allocate the thunk structure here, where we can fail gracefully.
+               BOOL result = m_thunk.Init(NULL, NULL);
+               if (result == FALSE)
+               {
+                       SetLastError(ERROR_OUTOFMEMORY);
+                       return -1;
+               }
+#endif // (_ATL_VER >= 0x0800)
+
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, pT);
+
+#ifdef _DEBUG
+               m_bModal = true;
+#endif // _DEBUG
+
+               return ::DialogBoxIndirectParam(ModuleHelper::GetResourceInstance(), m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
+       }
+
+       HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->m_hWnd == NULL);
+
+               if (!m_Template.IsValid())
+                       CreateTemplate();
+
+#if (_ATL_VER >= 0x0800)
+               // Allocate the thunk structure here, where we can fail gracefully.
+               BOOL result = m_thunk.Init(NULL, NULL);
+               if (result == FALSE) 
+               {
+                       SetLastError(ERROR_OUTOFMEMORY);
+                       return NULL;
+               }
+#endif // (_ATL_VER >= 0x0800)
+
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, pT);
+
+#ifdef _DEBUG
+               m_bModal = false;
+#endif // _DEBUG
+
+               HWND hWnd = ::CreateDialogIndirectParam(ModuleHelper::GetResourceInstance(), (LPCDLGTEMPLATE)m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
+               ATLASSERT(m_hWnd == hWnd);
+
+               return hWnd;
+       }
+
+       // for CComControl
+       HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
+       {
+               return Create(hWndParent, dwInitParam);
+       }
+
+       void DoInitTemplate() 
+       {
+               ATLASSERT(FALSE);   // MUST be defined in derived class
+       }
+
+       void DoInitControls() 
+       {
+               ATLASSERT(FALSE);   // MUST be defined in derived class
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CPropertySheetWindow - client side for a property sheet
+
+class CPropertySheetWindow : public ATL::CWindow
+{
+public:
+// Constructors
+       CPropertySheetWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd)
+       { }
+
+       CPropertySheetWindow& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Attributes
+       int GetPageCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HWND hWndTabCtrl = GetTabControl();
+               ATLASSERT(hWndTabCtrl != NULL);
+               return (int)::SendMessage(hWndTabCtrl, TCM_GETITEMCOUNT, 0, 0L);
+       }
+
+       HWND GetActivePage() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0L);
+       }
+
+       int GetActiveIndex() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               HWND hWndTabCtrl = GetTabControl();
+               ATLASSERT(hWndTabCtrl != NULL);
+               return (int)::SendMessage(hWndTabCtrl, TCM_GETCURSEL, 0, 0L);
+       }
+
+       BOOL SetActivePage(int nPageIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, nPageIndex, 0L);
+       }
+
+       BOOL SetActivePage(HPROPSHEETPAGE hPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hPage != NULL);
+               return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, 0, (LPARAM)hPage);
+       }
+
+       BOOL SetActivePageByID(int nPageID)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSELID, 0, nPageID);
+       }
+
+       void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
+               ATLASSERT(lpszText != NULL);
+               ::SendMessage(m_hWnd, PSM_SETTITLE, nStyle, (LPARAM)lpszText);
+       }
+
+       HWND GetTabControl() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0L);
+       }
+
+       void SetFinishText(LPCTSTR lpszText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText);
+       }
+
+       void SetWizardButtons(DWORD dwFlags)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags);
+       }
+
+// Operations
+       BOOL AddPage(HPROPSHEETPAGE hPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hPage != NULL);
+               return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
+       }
+
+       BOOL AddPage(LPCPROPSHEETPAGE pPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pPage != NULL);
+               HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
+               if(hPage == NULL)
+                       return FALSE;
+               return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL InsertPage(int nNewPageIndex, HPROPSHEETPAGE hPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hPage != NULL);
+               return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage);
+       }
+
+       BOOL InsertPage(int nNewPageIndex, LPCPROPSHEETPAGE pPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pPage != NULL);
+               HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
+               if(hPage == NULL)
+                       return FALSE;
+               return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage);
+       }
+
+       BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, HPROPSHEETPAGE hPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hPage != NULL);
+               return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage);
+       }
+
+       BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, LPCPROPSHEETPAGE pPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pPage != NULL);
+               HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
+               if(hPage == NULL)
+                       return FALSE;
+               return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage);
+       }
+#endif // !_WIN32_WCE
+
+       void RemovePage(int nPageIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_REMOVEPAGE, nPageIndex, 0L);
+       }
+
+       void RemovePage(HPROPSHEETPAGE hPage)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(hPage != NULL);
+               ::SendMessage(m_hWnd, PSM_REMOVEPAGE, 0, (LPARAM)hPage);
+       }
+
+       BOOL PressButton(int nButton)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0L);
+       }
+
+       BOOL Apply()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, PSM_APPLY, 0, 0L);
+       }
+
+       void CancelToClose()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_CANCELTOCLOSE, 0, 0L);
+       }
+
+       void SetModified(HWND hWndPage, BOOL bChanged = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(::IsWindow(hWndPage));
+               UINT uMsg = bChanged ? PSM_CHANGED : PSM_UNCHANGED;
+               ::SendMessage(m_hWnd, uMsg, (WPARAM)hWndPage, 0L);
+       }
+
+       LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SendMessage(m_hWnd, PSM_QUERYSIBLINGS, wParam, lParam);
+       }
+
+       void RebootSystem()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_REBOOTSYSTEM, 0, 0L);
+       }
+
+       void RestartWindows()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_RESTARTWINDOWS, 0, 0L);
+       }
+
+       BOOL IsDialogMessage(LPMSG lpMsg)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, PSM_ISDIALOGMESSAGE, 0, (LPARAM)lpMsg);
+       }
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       int HwndToIndex(HWND hWnd) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PSM_HWNDTOINDEX, (WPARAM)hWnd, 0L);
+       }
+
+       HWND IndexToHwnd(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HWND)::SendMessage(m_hWnd, PSM_INDEXTOHWND, nIndex, 0L);
+       }
+
+       int PageToIndex(HPROPSHEETPAGE hPage) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PSM_PAGETOINDEX, 0, (LPARAM)hPage);
+       }
+
+       HPROPSHEETPAGE IndexToPage(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HPROPSHEETPAGE)::SendMessage(m_hWnd, PSM_INDEXTOPAGE, nIndex, 0L);
+       }
+
+       int IdToIndex(int nID) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PSM_IDTOINDEX, 0, nID);
+       }
+
+       int IndexToId(int nIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PSM_INDEXTOID, nIndex, 0L);
+       }
+
+       int GetResult() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, PSM_GETRESULT, 0, 0L);
+       }
+
+       BOOL RecalcPageSizes()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, PSM_RECALCPAGESIZES, 0, 0L);
+       }
+
+       void SetHeaderTitle(int nIndex, LPCTSTR lpstrHeaderTitle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_SETHEADERTITLE, nIndex, (LPARAM)lpstrHeaderTitle);
+       }
+
+       void SetHeaderSubTitle(int nIndex, LPCTSTR lpstrHeaderSubTitle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_SETHEADERSUBTITLE, nIndex, (LPARAM)lpstrHeaderSubTitle);
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+// Implementation - override to prevent usage
+       HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
+       {
+               ATLASSERT(FALSE);
+               return NULL;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CPropertySheetImpl - implements a property sheet
+
+template <class T, class TBase = CPropertySheetWindow>
+class ATL_NO_VTABLE CPropertySheetImpl : public ATL::CWindowImplBaseT< TBase >
+{
+public:
+       PROPSHEETHEADER m_psh;
+       ATL::CSimpleArray<HPROPSHEETPAGE> m_arrPages;
+
+#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
+  #ifndef PROPSHEET_LINK_SIZE
+       #define PROPSHEET_LINK_SIZE 128
+  #endif // PROPSHEET_LINK_SIZE
+       TCHAR m_szLink[PROPSHEET_LINK_SIZE];
+       static LPCTSTR m_pszTitle;
+       static LPCTSTR m_pszLink;
+#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) 
+
+// Construction/Destruction
+       CPropertySheetImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
+       {
+               memset(&m_psh, 0, sizeof(PROPSHEETHEADER));
+               m_psh.dwSize = sizeof(PROPSHEETHEADER);
+               m_psh.dwFlags = PSH_USECALLBACK;
+               m_psh.hInstance = ModuleHelper::GetResourceInstance();
+               m_psh.phpage = NULL;   // will be set later
+               m_psh.nPages = 0;      // will be set later
+               m_psh.pszCaption = title.m_lpstr;
+               m_psh.nStartPage = uStartPage;
+               m_psh.hwndParent = hWndParent;   // if NULL, will be set in DoModal/Create
+               m_psh.pfnCallback = T::PropSheetCallback;
+
+#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific 
+               m_psh.dwFlags |= PSH_MAXIMIZE;
+               m_szLink[0] = 0;
+#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
+       }
+
+       ~CPropertySheetImpl()
+       {
+               if(m_arrPages.GetSize() > 0)   // sheet never created, destroy all pages
+               {
+                       for(int i = 0; i < m_arrPages.GetSize(); i++)
+                               ::DestroyPropertySheetPage((HPROPSHEETPAGE)m_arrPages[i]);
+               }
+       }
+
+// Callback function and overrideables
+       static int CALLBACK PropSheetCallback(HWND hWnd, UINT uMsg, LPARAM lParam)
+       {
+               lParam;   // avoid level 4 warning
+               int nRet = 0;
+
+               if(uMsg == PSCB_INITIALIZED)
+               {
+                       ATLASSERT(hWnd != NULL);
+                       T* pT = (T*)ModuleHelper::ExtractCreateWndData();
+                       // subclass the sheet window
+                       pT->SubclassWindow(hWnd);
+                       // remove page handles array
+                       pT->_CleanUpPages();
+
+#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
+                       m_pszTitle = pT->m_psh.pszCaption;
+                       if(*pT->m_szLink != 0)
+                               m_pszLink = pT->m_szLink;
+#endif  // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
+
+                       pT->OnSheetInitialized();
+               }
+#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific uMsg
+               else
+               {
+                       switch(uMsg)
+                       {
+                       case PSCB_GETVERSION :
+                               nRet = COMCTL32_VERSION;
+                               break;
+                       case PSCB_GETTITLE :
+                               if(m_pszTitle != NULL)
+                               {
+                                       lstrcpy((LPTSTR)lParam, m_pszTitle);
+                                       m_pszTitle = NULL;
+                               }
+                               break;
+                       case PSCB_GETLINKTEXT:
+                               if(m_pszLink != NULL)
+                               {
+                                       lstrcpy((LPTSTR)lParam, m_pszLink);
+                                       m_pszLink = NULL;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) 
+
+               return nRet;
+       }
+
+       void OnSheetInitialized()
+       {
+       }
+
+// Create method
+       HWND Create(HWND hWndParent = NULL)
+       {
+               ATLASSERT(m_hWnd == NULL);
+
+               m_psh.dwFlags |= PSH_MODELESS;
+               if(m_psh.hwndParent == NULL)
+                       m_psh.hwndParent = hWndParent;
+               m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
+               m_psh.nPages = m_arrPages.GetSize();
+
+               T* pT = static_cast<T*>(this);
+               ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT);
+
+               HWND hWnd = (HWND)::PropertySheet(&m_psh);
+               _CleanUpPages();   // ensure clean-up, required if call failed
+
+               ATLASSERT(m_hWnd == hWnd);
+
+               return hWnd;
+       }
+
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
+       {
+               ATLASSERT(m_hWnd == NULL);
+
+               m_psh.dwFlags &= ~PSH_MODELESS;
+               if(m_psh.hwndParent == NULL)
+                       m_psh.hwndParent = hWndParent;
+               m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
+               m_psh.nPages = m_arrPages.GetSize();
+
+               T* pT = static_cast<T*>(this);
+               ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT);
+
+               INT_PTR nRet = ::PropertySheet(&m_psh);
+               _CleanUpPages();   // ensure clean-up, required if call failed
+
+               return nRet;
+       }
+
+       // implementation helper - clean up pages array
+       void _CleanUpPages()
+       {
+               m_psh.nPages = 0;
+               m_psh.phpage = NULL;
+               m_arrPages.RemoveAll();
+       }
+
+// Attributes (extended overrides of client class methods)
+// These now can be called before the sheet is created
+// Note: Calling these after the sheet is created gives unpredictable results
+       int GetPageCount() const
+       {
+               if(m_hWnd == NULL)   // not created yet
+                       return m_arrPages.GetSize();
+               return TBase::GetPageCount();
+       }
+
+       int GetActiveIndex() const
+       {
+               if(m_hWnd == NULL)   // not created yet
+                       return m_psh.nStartPage;
+               return TBase::GetActiveIndex();
+       }
+
+       HPROPSHEETPAGE GetPage(int nPageIndex) const
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+               return (HPROPSHEETPAGE)m_arrPages[nPageIndex];
+       }
+
+       int GetPageIndex(HPROPSHEETPAGE hPage) const
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+               return m_arrPages.Find((HPROPSHEETPAGE&)hPage);
+       }
+
+       BOOL SetActivePage(int nPageIndex)
+       {
+               if(m_hWnd == NULL)   // not created yet
+               {
+                       ATLASSERT(nPageIndex >= 0 && nPageIndex < m_arrPages.GetSize());
+                       m_psh.nStartPage = nPageIndex;
+                       return TRUE;
+               }
+               return TBase::SetActivePage(nPageIndex);
+       }
+
+       BOOL SetActivePage(HPROPSHEETPAGE hPage)
+       {
+               ATLASSERT(hPage != NULL);
+               if (m_hWnd == NULL)   // not created yet
+               {
+                       int nPageIndex = GetPageIndex(hPage);
+                       if(nPageIndex == -1)
+                               return FALSE;
+
+                       return SetActivePage(nPageIndex);
+               }
+               return TBase::SetActivePage(hPage);
+
+       }
+
+       void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
+       {
+               ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0);   // only PSH_PROPTITLE is valid
+               ATLASSERT(lpszText != NULL);
+
+               if(m_hWnd == NULL)
+               {
+                       // set internal state
+                       m_psh.pszCaption = lpszText;   // must exist until sheet is created
+                       m_psh.dwFlags &= ~PSH_PROPTITLE;
+                       m_psh.dwFlags |= nStyle;
+               }
+               else
+               {
+                       // set external state
+                       TBase::SetTitle(lpszText, nStyle);
+               }
+       }
+
+#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific Link field        
+       void SetLinkText(LPCTSTR lpszText)
+       {
+               ATLASSERT(lpszText != NULL);
+               ATLASSERT(lstrlen(lpszText) < PROPSHEET_LINK_SIZE);
+               lstrcpy(m_szLink, lpszText);
+       }
+#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) 
+
+       void SetWizardMode()
+       {
+               m_psh.dwFlags |= PSH_WIZARD;
+       }
+
+       void EnableHelp()
+       {
+               m_psh.dwFlags |= PSH_HASHELP;
+       }
+
+// Operations
+       BOOL AddPage(HPROPSHEETPAGE hPage)
+       {
+               ATLASSERT(hPage != NULL);
+               BOOL bRet = FALSE;
+               if(m_hWnd != NULL)
+                       bRet = TBase::AddPage(hPage);
+               else    // sheet not created yet, use internal data
+                       bRet = m_arrPages.Add((HPROPSHEETPAGE&)hPage);
+               return bRet;
+       }
+
+       BOOL AddPage(LPCPROPSHEETPAGE pPage)
+       {
+               ATLASSERT(pPage != NULL);
+               HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
+               if(hPage == NULL)
+                       return FALSE;
+               BOOL bRet = AddPage(hPage);
+               if(!bRet)
+                       ::DestroyPropertySheetPage(hPage);
+               return bRet;
+       }
+
+       BOOL RemovePage(HPROPSHEETPAGE hPage)
+       {
+               ATLASSERT(hPage != NULL);
+               if (m_hWnd == NULL)   // not created yet
+               {
+                       int nPage = GetPageIndex(hPage);
+                       if(nPage == -1)
+                               return FALSE;
+                       return RemovePage(nPage);
+               }
+               TBase::RemovePage(hPage);
+               return TRUE;
+
+       }
+
+       BOOL RemovePage(int nPageIndex)
+       {
+               BOOL bRet = TRUE;
+               if(m_hWnd != NULL)
+                       TBase::RemovePage(nPageIndex);
+               else    // sheet not created yet, use internal data
+                       bRet = m_arrPages.RemoveAt(nPageIndex);
+               return bRet;
+       }
+
+#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+       void SetHeader(LPCTSTR szbmHeader)
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+
+               m_psh.dwFlags &= ~PSH_WIZARD;
+               m_psh.dwFlags |= (PSH_HEADER | PSH_WIZARD97);
+               m_psh.pszbmHeader = szbmHeader;
+       }
+
+       void SetHeader(HBITMAP hbmHeader)
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+
+               m_psh.dwFlags &= ~PSH_WIZARD;
+               m_psh.dwFlags |= (PSH_HEADER | PSH_USEHBMHEADER | PSH_WIZARD97);
+               m_psh.hbmHeader = hbmHeader;
+       }
+
+       void SetWatermark(LPCTSTR szbmWatermark, HPALETTE hplWatermark = NULL)
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+
+               m_psh.dwFlags &= ~PSH_WIZARD;
+               m_psh.dwFlags |= PSH_WATERMARK | PSH_WIZARD97;
+               m_psh.pszbmWatermark = szbmWatermark;
+
+               if (hplWatermark != NULL)
+               {
+                       m_psh.dwFlags |= PSH_USEHPLWATERMARK;
+                       m_psh.hplWatermark = hplWatermark;
+               }
+       }
+
+       void SetWatermark(HBITMAP hbmWatermark, HPALETTE hplWatermark = NULL)
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+
+               m_psh.dwFlags &= ~PSH_WIZARD;
+               m_psh.dwFlags |= (PSH_WATERMARK | PSH_USEHBMWATERMARK | PSH_WIZARD97);
+               m_psh.hbmWatermark = hbmWatermark;
+
+               if (hplWatermark != NULL)
+               {
+                       m_psh.dwFlags |= PSH_USEHPLWATERMARK;
+                       m_psh.hplWatermark = hplWatermark;
+               }
+       }
+
+       void StretchWatermark(bool bStretchWatermark)
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+               if (bStretchWatermark)
+                       m_psh.dwFlags |= PSH_STRETCHWATERMARK;
+               else
+                       m_psh.dwFlags &= ~PSH_STRETCHWATERMARK;
+       }
+#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CPropertySheetImpl)
+               MESSAGE_HANDLER(WM_COMMAND, OnCommand)
+               MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
+       END_MSG_MAP()
+
+       LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) &&
+                  ((m_psh.dwFlags & PSH_MODELESS) != 0) && (GetActivePage() == NULL))
+                       DestroyWindow();
+               return lRet;
+       }
+
+       LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(((m_psh.dwFlags & PSH_MODELESS) == PSH_MODELESS) && ((wParam & 0xFFF0) == SC_CLOSE))
+                       SendMessage(WM_CLOSE);
+               else
+                       bHandled = FALSE;
+               return 0;
+       }
+};
+
+#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC static pointers
+template < class T, class TBase >
+LPCWSTR CPropertySheetImpl<T,TBase>::m_pszTitle = NULL;
+template < class T, class TBase>
+LPCWSTR CPropertySheetImpl<T,TBase>::m_pszLink = NULL;
+#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
+
+// for non-customized sheets
+class CPropertySheet : public CPropertySheetImpl<CPropertySheet>
+{
+public:
+       CPropertySheet(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
+               : CPropertySheetImpl<CPropertySheet>(title, uStartPage, hWndParent)
+       { }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPropertyPageWindow - client side for a property page
+
+class CPropertyPageWindow : public ATL::CWindow
+{
+public:
+// Constructors
+       CPropertyPageWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd)
+       { }
+
+       CPropertyPageWindow& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Attributes
+       CPropertySheetWindow GetPropertySheet() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CPropertySheetWindow(GetParent());
+       }
+
+// Operations
+       BOOL Apply()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               return GetPropertySheet().Apply();
+       }
+
+       void CancelToClose()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetPropertySheet().CancelToClose();
+       }
+
+       void SetModified(BOOL bChanged = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetPropertySheet().SetModified(m_hWnd, bChanged);
+       }
+
+       LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               return GetPropertySheet().QuerySiblings(wParam, lParam);
+       }
+
+       void RebootSystem()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetPropertySheet().RebootSystem();
+       }
+
+       void RestartWindows()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetPropertySheet().RestartWindows();
+       }
+
+       void SetWizardButtons(DWORD dwFlags)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetPropertySheet().SetWizardButtons(dwFlags);
+       }
+
+// Implementation - overrides to prevent usage
+       HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
+       {
+               ATLASSERT(FALSE);
+               return NULL;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CPropertyPageImpl - implements a property page
+
+template <class T, class TBase = CPropertyPageWindow>
+class ATL_NO_VTABLE CPropertyPageImpl : public ATL::CDialogImplBaseT< TBase >
+{
+public:
+       PROPSHEETPAGE m_psp;
+
+       operator PROPSHEETPAGE*() { return &m_psp; }
+
+// Construction
+       CPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL)
+       {
+               // initialize PROPSHEETPAGE struct
+               memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
+               m_psp.dwSize = sizeof(PROPSHEETPAGE);
+               m_psp.dwFlags = PSP_USECALLBACK;
+               m_psp.hInstance = ModuleHelper::GetResourceInstance();
+               T* pT = static_cast<T*>(this);
+               m_psp.pszTemplate = MAKEINTRESOURCE(pT->IDD);
+               m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc;
+               m_psp.pfnCallback = T::PropPageCallback;
+               m_psp.lParam = (LPARAM)pT;
+
+               if(title.m_lpstr != NULL)
+                       SetTitle(title);
+       }
+
+// Callback function and overrideables
+       static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
+       {
+               hWnd;   // avoid level 4 warning
+               ATLASSERT(hWnd == NULL);
+               T* pT = (T*)ppsp->lParam;
+               UINT uRet = 0;
+
+               switch(uMsg)
+               {
+               case PSPCB_CREATE:
+                       {
+                               ATL::CDialogImplBaseT< TBase >* pPage = (ATL::CDialogImplBaseT< TBase >*)pT;
+                               ModuleHelper::AddCreateWndData(&pPage->m_thunk.cd, pPage);
+                               uRet = pT->OnPageCreate() ? 1 : 0;
+                       }
+                       break;
+#if (_WIN32_IE >= 0x0500)
+               case PSPCB_ADDREF:
+                       pT->OnPageAddRef();
+                       break;
+#endif // (_WIN32_IE >= 0x0500)
+               case PSPCB_RELEASE:
+                       pT->OnPageRelease();
+                       break;
+               default:
+                       break;
+               }
+
+               return uRet;
+       }
+
+       bool OnPageCreate()
+       {
+               return true;   // true - allow page to be created, false - prevent creation
+       }
+
+#if (_WIN32_IE >= 0x0500)
+       void OnPageAddRef()
+       {
+       }
+#endif // (_WIN32_IE >= 0x0500)
+
+       void OnPageRelease()
+       {
+       }
+
+// Create method
+       HPROPSHEETPAGE Create()
+       {
+               return ::CreatePropertySheetPage(&m_psp);
+       }
+
+// Attributes
+       void SetTitle(ATL::_U_STRINGorID title)
+       {
+               m_psp.pszTitle = title.m_lpstr;
+               m_psp.dwFlags |= PSP_USETITLE;
+       }
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       void SetHeaderTitle(LPCTSTR lpstrHeaderTitle)
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+               m_psp.dwFlags |= PSP_USEHEADERTITLE;
+               m_psp.pszHeaderTitle = lpstrHeaderTitle;
+       }
+
+       void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle)
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+               m_psp.dwFlags |= PSP_USEHEADERSUBTITLE;
+               m_psp.pszHeaderSubTitle = lpstrHeaderSubTitle;
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+// Operations
+       void EnableHelp()
+       {
+               m_psp.dwFlags |= PSP_HASHELP;
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CPropertyPageImpl)
+               MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
+       END_MSG_MAP()
+
+       // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification
+       // handlers that return direct values without any restrictions
+       LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+#ifndef _WIN32_WCE
+               // This notification is sometimes received on Windows CE after the window is already destroyed
+               ATLASSERT(::IsWindow(m_hWnd));
+#endif
+               NMHDR* pNMHDR = (NMHDR*)lParam;
+
+               // don't handle messages not from the page/sheet itself
+               if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+#ifdef _WIN32_WCE
+               ATLASSERT(::IsWindow(m_hWnd));
+#endif
+
+               T* pT = static_cast<T*>(this);
+               LRESULT lResult = 0;
+               switch(pNMHDR->code)
+               {
+#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
+               case PSN_SETACTIVE:
+                       lResult = pT->OnSetActive();
+                       break;
+               case PSN_KILLACTIVE:
+                       lResult = pT->OnKillActive();
+                       break;
+               case PSN_APPLY:
+                       lResult = pT->OnApply();
+                       break;
+               case PSN_RESET:
+                       pT->OnReset();
+                       break;
+               case PSN_QUERYCANCEL:
+                       lResult = pT->OnQueryCancel();
+                       break;
+               case PSN_WIZNEXT:
+                       lResult = pT->OnWizardNext();
+                       break;
+               case PSN_WIZBACK:
+                       lResult = pT->OnWizardBack();
+                       break;
+               case PSN_WIZFINISH:
+                       lResult = pT->OnWizardFinish();
+                       break;
+               case PSN_HELP:
+                       pT->OnHelp();
+                       break;
+#ifndef _WIN32_WCE
+#if (_WIN32_IE >= 0x0400)
+               case PSN_GETOBJECT:
+                       if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
+                               bHandled = FALSE;
+                       break;
+#endif // (_WIN32_IE >= 0x0400)
+#if (_WIN32_IE >= 0x0500)
+               case PSN_TRANSLATEACCELERATOR:
+                       {
+                               LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
+                               lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam);
+                       }
+                       break;
+               case PSN_QUERYINITIALFOCUS:
+                       {
+                               LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
+                               lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
+                       }
+                       break;
+#endif // (_WIN32_IE >= 0x0500)
+#endif // !_WIN32_WCE
+
+#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
+               case PSN_SETACTIVE:
+                       lResult = pT->OnSetActive() ? 0 : -1;
+                       break;
+               case PSN_KILLACTIVE:
+                       lResult = !pT->OnKillActive();
+                       break;
+               case PSN_APPLY:
+                       lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
+                       break;
+               case PSN_RESET:
+                       pT->OnReset();
+                       break;
+               case PSN_QUERYCANCEL:
+                       lResult = !pT->OnQueryCancel();
+                       break;
+               case PSN_WIZNEXT:
+                       lResult = pT->OnWizardNext();
+                       break;
+               case PSN_WIZBACK:
+                       lResult = pT->OnWizardBack();
+                       break;
+               case PSN_WIZFINISH:
+                       lResult = !pT->OnWizardFinish();
+                       break;
+               case PSN_HELP:
+                       pT->OnHelp();
+                       break;
+#ifndef _WIN32_WCE
+#if (_WIN32_IE >= 0x0400)
+               case PSN_GETOBJECT:
+                       if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
+                               bHandled = FALSE;
+                       break;
+#endif // (_WIN32_IE >= 0x0400)
+#if (_WIN32_IE >= 0x0500)
+               case PSN_TRANSLATEACCELERATOR:
+                       {
+                               LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
+                               lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
+                       }
+                       break;
+               case PSN_QUERYINITIALFOCUS:
+                       {
+                               LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
+                               lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
+                       }
+                       break;
+#endif // (_WIN32_IE >= 0x0500)
+#endif // !_WIN32_WCE
+
+#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
+               default:
+                       bHandled = FALSE;   // not handled
+               }
+
+               return lResult;
+       }
+
+// Overridables
+       // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification
+       // handlers that return direct values without any restrictions
+#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
+       int OnSetActive()
+       {
+               // 0 = allow activate
+               // -1 = go back that was active
+               // page ID = jump to page
+               return 0;
+       }
+
+       BOOL OnKillActive()
+       {
+               // FALSE = allow deactivate
+               // TRUE = prevent deactivation
+               return FALSE;
+       }
+
+       int OnApply()
+       {
+               // PSNRET_NOERROR = apply OK
+               // PSNRET_INVALID = apply not OK, return to this page
+               // PSNRET_INVALID_NOCHANGEPAGE = apply not OK, don't change focus
+               return PSNRET_NOERROR;
+       }
+
+       void OnReset()
+       {
+       }
+
+       BOOL OnQueryCancel()
+       {
+               // FALSE = allow cancel
+               // TRUE = prevent cancel
+               return FALSE;
+       }
+
+       int OnWizardBack()
+       {
+               // 0  = goto previous page
+               // -1 = prevent page change
+               // >0 = jump to page by dlg ID
+               return 0;
+       }
+
+       int OnWizardNext()
+       {
+               // 0  = goto next page
+               // -1 = prevent page change
+               // >0 = jump to page by dlg ID
+               return 0;
+       }
+
+       INT_PTR OnWizardFinish()
+       {
+               // FALSE = allow finish
+               // TRUE = prevent finish
+               // HWND = prevent finish and set focus to HWND (CommCtrl 5.80 only)
+               return FALSE;
+       }
+
+       void OnHelp()
+       {
+       }
+
+#ifndef _WIN32_WCE
+#if (_WIN32_IE >= 0x0400)
+       BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
+       {
+               return FALSE;   // not processed
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500)
+       int OnTranslateAccelerator(LPMSG /*lpMsg*/)
+       {
+               // PSNRET_NOERROR - message not handled
+               // PSNRET_MESSAGEHANDLED - message handled
+               return PSNRET_NOERROR;
+       }
+
+       HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
+       {
+               // NULL = set focus to default control
+               // HWND = set focus to HWND
+               return NULL;
+       }
+#endif // (_WIN32_IE >= 0x0500)
+#endif // !_WIN32_WCE
+
+#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
+       BOOL OnSetActive()
+       {
+               return TRUE;
+       }
+
+       BOOL OnKillActive()
+       {
+               return TRUE;
+       }
+
+       BOOL OnApply()
+       {
+               return TRUE;
+       }
+
+       void OnReset()
+       {
+       }
+
+       BOOL OnQueryCancel()
+       {
+               return TRUE;    // ok to cancel
+       }
+
+       int OnWizardBack()
+       {
+               // 0  = goto previous page
+               // -1 = prevent page change
+               // >0 = jump to page by dlg ID
+               return 0;
+       }
+
+       int OnWizardNext()
+       {
+               // 0  = goto next page
+               // -1 = prevent page change
+               // >0 = jump to page by dlg ID
+               return 0;
+       }
+
+       BOOL OnWizardFinish()
+       {
+               return TRUE;
+       }
+
+       void OnHelp()
+       {
+       }
+
+#ifndef _WIN32_WCE
+#if (_WIN32_IE >= 0x0400)
+       BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
+       {
+               return FALSE;   // not processed
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500)
+       BOOL OnTranslateAccelerator(LPMSG /*lpMsg*/)
+       {
+               return FALSE;   // not translated
+       }
+
+       HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
+       {
+               return NULL;   // default
+       }
+#endif // (_WIN32_IE >= 0x0500)
+#endif // !_WIN32_WCE
+
+#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
+};
+
+// for non-customized pages
+template <WORD t_wDlgTemplateID>
+class CPropertyPage : public CPropertyPageImpl<CPropertyPage<t_wDlgTemplateID> >
+{
+public:
+       enum { IDD = t_wDlgTemplateID };
+
+       CPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<CPropertyPage>(title)
+       { }
+
+       DECLARE_EMPTY_MSG_MAP()
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CAxPropertyPageImpl - property page that hosts ActiveX controls
+
+#ifndef _ATL_NO_HOSTING
+
+// Note: You must #include <atlhost.h> to use these classes
+
+template <class T, class TBase = CPropertyPageWindow>
+class ATL_NO_VTABLE CAxPropertyPageImpl : public CPropertyPageImpl< T, TBase >
+{
+public:
+// Data members
+       HGLOBAL m_hInitData;
+       HGLOBAL m_hDlgRes;
+       HGLOBAL m_hDlgResSplit;
+
+// Constructor/destructor
+       CAxPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : 
+                       CPropertyPageImpl< T, TBase >(title),
+                       m_hInitData(NULL), m_hDlgRes(NULL), m_hDlgResSplit(NULL)
+       {
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+
+               // initialize ActiveX hosting and modify dialog template
+               ATL::AtlAxWinInit();
+
+               HINSTANCE hInstance = ModuleHelper::GetResourceInstance();
+               LPCTSTR lpTemplateName = MAKEINTRESOURCE(pT->IDD);
+               HRSRC hDlg = ::FindResource(hInstance, lpTemplateName, (LPTSTR)RT_DIALOG);
+               if(hDlg != NULL)
+               {
+                       HRSRC hDlgInit = ::FindResource(hInstance, lpTemplateName, (LPTSTR)_ATL_RT_DLGINIT);
+
+                       BYTE* pInitData = NULL;
+                       if(hDlgInit != NULL)
+                       {
+                               m_hInitData = ::LoadResource(hInstance, hDlgInit);
+                               pInitData = (BYTE*)::LockResource(m_hInitData);
+                       }
+
+                       m_hDlgRes = ::LoadResource(hInstance, hDlg);
+                       DLGTEMPLATE* pDlg = (DLGTEMPLATE*)::LockResource(m_hDlgRes);
+                       LPCDLGTEMPLATE lpDialogTemplate = ATL::_DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
+                       if(lpDialogTemplate != pDlg)
+                               m_hDlgResSplit = GlobalHandle(lpDialogTemplate);
+
+                       // set up property page to use in-memory dialog template
+                       if(lpDialogTemplate != NULL)
+                       {
+                               m_psp.dwFlags |= PSP_DLGINDIRECT;
+                               m_psp.pResource = lpDialogTemplate;
+                       }
+                       else
+                       {
+                               ATLASSERT(FALSE && _T("CAxPropertyPageImpl - ActiveX initializtion failed!"));
+                       }
+               }
+               else
+               {
+                       ATLASSERT(FALSE && _T("CAxPropertyPageImpl - Cannot find dialog template!"));
+               }
+       }
+
+       ~CAxPropertyPageImpl()
+       {
+               if(m_hInitData != NULL)
+               {
+                       UnlockResource(m_hInitData);
+                       FreeResource(m_hInitData);
+               }
+               if(m_hDlgRes != NULL)
+               {
+                       UnlockResource(m_hDlgRes);
+                       FreeResource(m_hDlgRes);
+               }
+               if(m_hDlgResSplit != NULL)
+               {
+                       ::GlobalFree(m_hDlgResSplit);
+               }
+       }
+
+// Methods
+       // call this one to handle keyboard message for ActiveX controls
+       BOOL PreTranslateMessage(LPMSG pMsg)
+       {
+               if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+               // find a direct child of the dialog from the window that has focus
+               HWND hWndCtl = ::GetFocus();
+               if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd)
+               {
+                       do
+                       {
+                               hWndCtl = ::GetParent(hWndCtl);
+                       }
+                       while (::GetParent(hWndCtl) != m_hWnd);
+               }
+               // give controls a chance to translate this message
+               return (BOOL)::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg);
+       }
+
+// Overridables
+#if (_WIN32_IE >= 0x0500)
+       // new default implementation for ActiveX hosting pages
+#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
+       int OnTranslateAccelerator(LPMSG lpMsg)
+       {
+               T* pT = static_cast<T*>(this);
+               return (pT->PreTranslateMessage(lpMsg) != FALSE) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
+       }
+#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
+       BOOL OnTranslateAccelerator(LPMSG lpMsg)
+       {
+               T* pT = static_cast<T*>(this);
+               return pT->PreTranslateMessage(lpMsg);
+       }
+#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
+#endif // (_WIN32_IE >= 0x0500)
+
+// Support for new stuff in ATL7
+#if (_ATL_VER >= 0x0700)
+       int GetIDD()
+       {
+               return( static_cast<T*>(this)->IDD );
+       }
+
+       virtual DLGPROC GetDialogProc()
+       {
+               return DialogProc;
+       }
+
+       static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               CAxPropertyPageImpl< T, TBase >* pThis = (CAxPropertyPageImpl< T, TBase >*)hWnd;
+               if (uMsg == WM_INITDIALOG)
+               {
+                       HRESULT hr;
+                       if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD())))
+                       {
+                               ATLASSERT(FALSE);
+                               return FALSE;
+                       }
+               }
+               return CPropertyPageImpl< T, TBase >::DialogProc(hWnd, uMsg, wParam, lParam);
+       }
+
+// ActiveX controls creation
+       virtual HRESULT CreateActiveXControls(UINT nID)
+       {
+               // Load dialog template and InitData
+               HRSRC hDlgInit = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT);
+               BYTE* pInitData = NULL;
+               HGLOBAL hData = NULL;
+               HRESULT hr = S_OK;
+               if (hDlgInit != NULL)
+               {
+                       hData = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlgInit);
+                       if (hData != NULL)
+                               pInitData = (BYTE*) ::LockResource(hData);
+               }
+
+               HRSRC hDlg = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG);
+               if (hDlg != NULL)
+               {
+                       HGLOBAL hResource = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlg);
+                       DLGTEMPLATE* pDlg = NULL;
+                       if (hResource != NULL)
+                       {
+                               pDlg = (DLGTEMPLATE*) ::LockResource(hResource);
+                               if (pDlg != NULL)
+                               {
+                                       // Get first control on the template
+                                       BOOL bDialogEx = ATL::_DialogSplitHelper::IsDialogEx(pDlg);
+                                       WORD nItems = ATL::_DialogSplitHelper::DlgTemplateItemCount(pDlg);
+
+                                       // Get first control on the dialog
+                                       DLGITEMTEMPLATE* pItem = ATL::_DialogSplitHelper::FindFirstDlgItem(pDlg);
+                                       HWND hWndPrev = GetWindow(GW_CHILD);
+
+                                       // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order)
+                                       for (WORD nItem = 0; nItem < nItems; nItem++)
+                                       {
+                                               DWORD wID = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id;
+                                               if (ATL::_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx))
+                                               {
+                                                       BYTE* pData = NULL;
+                                                       DWORD dwLen = ATL::_DialogSplitHelper::FindCreateData(wID, pInitData, &pData);
+                                                       ATL::CComPtr<IStream> spStream;
+                                                       if (dwLen != 0)
+                                                       {
+                                                               HGLOBAL h = GlobalAlloc(GHND, dwLen);
+                                                               if (h != NULL)
+                                                               {
+                                                                       BYTE* pBytes = (BYTE*) GlobalLock(h);
+                                                                       BYTE* pSource = pData; 
+                                                                       SecureHelper::memcpy_x(pBytes, dwLen, pSource, dwLen);
+                                                                       GlobalUnlock(h);
+                                                                       CreateStreamOnHGlobal(h, TRUE, &spStream);
+                                                               }
+                                                               else
+                                                               {
+                                                                       hr = E_OUTOFMEMORY;
+                                                                       break;
+                                                               }
+                                                       }
+
+                                                       ATL::CComBSTR bstrLicKey;
+                                                       hr = ATL::_DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str);
+                                                       if (SUCCEEDED(hr))
+                                                       {
+                                                               ATL::CAxWindow2 wnd;
+                                                               // Get control caption.
+                                                               LPWSTR pszClassName = 
+                                                                       bDialogEx ? 
+                                                                               (LPWSTR)(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) :
+                                                                               (LPWSTR)(pItem + 1);
+                                                               // Get control rect.
+                                                               RECT rect;
+                                                               rect.left = 
+                                                                       bDialogEx ? 
+                                                                               ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x : 
+                                                                               pItem->x;
+                                                               rect.top = 
+                                                                       bDialogEx ? 
+                                                                               ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y : 
+                                                                               pItem->y;
+                                                               rect.right = rect.left + 
+                                                                       (bDialogEx ? 
+                                                                               ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx : 
+                                                                               pItem->cx);
+                                                               rect.bottom = rect.top + 
+                                                                       (bDialogEx ? 
+                                                                               ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy : 
+                                                                               pItem->cy);
+
+                                                               // Convert from dialog units to screen units
+                                                               MapDialogRect(&rect);
+
+                                                               // Create AxWindow with a NULL caption.
+                                                               wnd.Create(m_hWnd, 
+                                                                       &rect, 
+                                                                       NULL, 
+                                                                       (bDialogEx ? 
+                                                                               ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style : 
+                                                                               pItem->style) | WS_TABSTOP, 
+                                                                       bDialogEx ? 
+                                                                               ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle : 
+                                                                               0,
+                                                                       bDialogEx ? 
+                                                                               ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : 
+                                                                               pItem->id,
+                                                                       NULL);
+
+                                                               if (wnd != NULL)
+                                                               {
+#ifndef _WIN32_WCE
+                                                                       // Set the Help ID
+                                                                       if (bDialogEx && ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0)
+                                                                               wnd.SetWindowContextHelpId(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID);
+#endif // !_WIN32_WCE
+                                                                       // Try to create the ActiveX control.
+                                                                       hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey);
+                                                                       if (FAILED(hr))
+                                                                               break;
+                                                                       // Set the correct tab position.
+                                                                       if (nItem == 0)
+                                                                               hWndPrev = HWND_TOP;
+                                                                       wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+                                                                       hWndPrev = wnd;
+                                                               }
+                                                               else
+                                                               {
+                                                                       hr = ATL::AtlHresultFromLastError();
+                                                               }
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       if (nItem != 0)
+                                                               hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT);
+                                               }
+                                               pItem = ATL::_DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx);
+                                       }
+                               }
+                               else
+                                       hr = ATL::AtlHresultFromLastError();
+                       }
+                       else
+                               hr = ATL::AtlHresultFromLastError();
+               }
+               return hr;
+       }
+
+// Event handling support
+       HRESULT AdviseSinkMap(bool bAdvise)
+       {
+               if(!bAdvise && m_hWnd == NULL)
+               {
+                       // window is gone, controls are already unadvised
+                       ATLTRACE2(atlTraceUI, 0, _T("CAxPropertyPageImpl::AdviseSinkMap called after the window was destroyed\n"));
+                       return S_OK;
+               }
+               HRESULT hRet = E_NOTIMPL;
+               __if_exists(T::_GetSinkMapFinder)
+               {
+                       T* pT = static_cast<T*>(this);
+                       hRet = AtlAdviseSinkMap(pT, bAdvise);
+               }
+               return hRet;
+       }
+
+// Message map and handlers
+       typedef CPropertyPageImpl< T, TBase>   _baseClass;
+       BEGIN_MSG_MAP(CAxPropertyPageImpl)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               CHAIN_MSG_MAP(_baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               // initialize controls in dialog with DLGINIT resource section
+               ExecuteDlgInit(static_cast<T*>(this)->IDD);
+               AdviseSinkMap(true);
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               AdviseSinkMap(false);
+               bHandled = FALSE;
+               return 1;
+       }
+#endif // (_ATL_VER >= 0x0700)
+};
+
+// for non-customized pages
+template <WORD t_wDlgTemplateID>
+class CAxPropertyPage : public CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >
+{
+public:
+       enum { IDD = t_wDlgTemplateID };
+
+       CAxPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl<CAxPropertyPage>(title)
+       { }
+
+#if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)
+       // not empty so we handle accelerators/create controls
+       BEGIN_MSG_MAP(CAxPropertyPage)
+               CHAIN_MSG_MAP(CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >)
+       END_MSG_MAP()
+#else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
+       DECLARE_EMPTY_MSG_MAP()
+#endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
+};
+
+#endif // _ATL_NO_HOSTING
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Wizard97 Support
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+// Sample wizard dialog resources:
+//
+// IDD_WIZ97_INTERIOR_BLANK DIALOG  0, 0, 317, 143
+// STYLE DS_SETFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
+// CAPTION "Wizard97 Property Page - Interior"
+// FONT 8, "MS Shell Dlg"
+// BEGIN
+// END
+//
+// IDD_WIZ97_EXTERIOR_BLANK DIALOGEX 0, 0, 317, 193
+// STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
+// CAPTION "Wizard97 Property Page - Welcome/Complete"
+// FONT 8, "MS Shell Dlg", 0, 0, 0x0
+// BEGIN
+//    LTEXT           "Welcome to the X Wizard",IDC_WIZ97_EXTERIOR_TITLE,115,8,
+//                    195,24
+//    LTEXT           "Wizard Explanation\r\n(The height of the static text should be in multiples of 8 dlus)",
+//                    IDC_STATIC,115,40,195,16
+//    LTEXT           "h",IDC_WIZ97_BULLET1,118,64,8,8
+//    LTEXT           "List Item 1 (the h is turned into a bullet)",IDC_STATIC,
+//                    127,63,122,8
+//    LTEXT           "h",IDC_WIZ97_BULLET2,118,79,8,8
+//    LTEXT           "List Item 2. Keep 7 dlus between paragraphs",IDC_STATIC,
+//                    127,78,33,8
+//    CONTROL         "&Do not show this Welcome page again",
+//                    IDC_WIZ97_WELCOME_NOTAGAIN,"Button",BS_AUTOCHECKBOX | 
+//                    WS_TABSTOP,115,169,138,10
+// END
+//
+// GUIDELINES DESIGNINFO 
+// BEGIN
+//    IDD_WIZ97_INTERIOR_BLANK, DIALOG
+//    BEGIN
+//        LEFTMARGIN, 7
+//        RIGHTMARGIN, 310
+//        VERTGUIDE, 21
+//        VERTGUIDE, 31
+//        VERTGUIDE, 286
+//        VERTGUIDE, 296
+//        TOPMARGIN, 7
+//        BOTTOMMARGIN, 136
+//        HORZGUIDE, 8
+//    END
+//
+//    IDD_WIZ97_EXTERIOR_BLANK, DIALOG
+//    BEGIN
+//        RIGHTMARGIN, 310
+//        VERTGUIDE, 115
+//        VERTGUIDE, 118
+//        VERTGUIDE, 127
+//        TOPMARGIN, 7
+//        BOTTOMMARGIN, 186
+//        HORZGUIDE, 8
+//        HORZGUIDE, 32
+//        HORZGUIDE, 40
+//        HORZGUIDE, 169
+//    END
+// END
+
+///////////////////////////////////////////////////////////////////////////////
+// CWizard97SheetWindow - client side for a Wizard 97 style wizard sheet
+
+class CWizard97SheetWindow : public CPropertySheetWindow
+{
+public:
+// Constructors
+       CWizard97SheetWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd)
+       { }
+
+       CWizard97SheetWindow& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Operations
+       HFONT GetExteriorPageTitleFont(void)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HFONT)::SendMessage(m_hWnd, GetMessage_GetExteriorPageTitleFont(), 0, 0L);
+       }
+
+       HFONT GetBulletFont(void)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HFONT)::SendMessage(m_hWnd, GetMessage_GetBulletFont(), 0, 0L);
+       }
+
+// Helpers
+       static UINT GetMessage_GetExteriorPageTitleFont()
+       {
+               static UINT uGetExteriorPageTitleFont = 0;
+               if(uGetExteriorPageTitleFont == 0)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont().\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(uGetExteriorPageTitleFont == 0)
+                               uGetExteriorPageTitleFont = ::RegisterWindowMessage(_T("GetExteriorPageTitleFont_531AF056-B8BE-4c4c-B786-AC608DF0DF12"));
+
+                       lock.Unlock();
+               }
+               ATLASSERT(uGetExteriorPageTitleFont != 0);
+               return uGetExteriorPageTitleFont;
+       }
+
+       static UINT GetMessage_GetBulletFont()
+       {
+               static UINT uGetBulletFont = 0;
+               if(uGetBulletFont == 0)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetBulletFont().\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(uGetBulletFont == 0)
+                               uGetBulletFont = ::RegisterWindowMessage(_T("GetBulletFont_AD347D08-8F65-45ef-982E-6352E8218AD5"));
+
+                       lock.Unlock();
+               }
+               ATLASSERT(uGetBulletFont != 0);
+               return uGetBulletFont;
+       }
+
+// Implementation - override to prevent usage
+       HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
+       {
+               ATLASSERT(FALSE);
+               return NULL;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CWizard97SheetImpl - implements a Wizard 97 style wizard sheet
+
+template <class T, class TBase = CWizard97SheetWindow>
+class ATL_NO_VTABLE CWizard97SheetImpl : public CPropertySheetImpl< T, TBase >
+{
+protected:
+// Typedefs
+       typedef CWizard97SheetImpl< T, TBase > thisClass;
+       typedef CPropertySheetImpl< T, TBase > baseClass;
+
+// Member variables
+       CFont m_fontExteriorPageTitle;   // Welcome and Completion page title font
+       CFont m_fontBullet;              // Bullet font (used on static text 'h' to produce a small bullet)
+       bool m_bReceivedFirstSizeMessage;   
+
+public:
+       CWizard97SheetImpl(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) :
+                       baseClass(title, uStartPage, hWndParent),
+                       m_bReceivedFirstSizeMessage(false)
+       {
+               m_psh.dwFlags &= ~(PSH_NOCONTEXTHELP);
+               m_psh.dwFlags &= ~(PSH_WIZARD | PSH_WIZARD_LITE);
+
+               m_psh.dwFlags |= (PSH_HASHELP | PSH_WIZARDCONTEXTHELP);
+               m_psh.dwFlags |= PSH_WIZARD97;
+
+               baseClass::SetHeader(headerBitmap.m_lpstr);
+               baseClass::SetWatermark(watermarkBitmap.m_lpstr);
+       }
+
+// Overrides from base class
+       void OnSheetInitialized()
+       {
+               T* pT = static_cast<T*>(this);
+               pT->_InitializeFonts();
+
+               // We'd like to center the wizard here, but its too early.
+               // Instead, we'll do CenterWindow upon our first WM_SIZE message
+       }
+
+// Initialization
+       void _InitializeFonts()
+       {
+               // Setup the Title and Bullet Font
+               // (Property pages can send the "get external page title font" and "get bullet font" messages)
+               // The derived class needs to do the actual SetFont for the dialog items)
+
+               CFontHandle fontThisDialog = this->GetFont();
+               CClientDC dcScreen(NULL);
+
+               LOGFONT titleLogFont = {0};
+               LOGFONT bulletLogFont = {0};
+               fontThisDialog.GetLogFont(&titleLogFont);
+               fontThisDialog.GetLogFont(&bulletLogFont);
+
+               // The Wizard 97 Spec recommends to do the Title Font
+               // as Verdana Bold, 12pt.
+               titleLogFont.lfCharSet = DEFAULT_CHARSET;
+               titleLogFont.lfWeight = FW_BOLD;
+               SecureHelper::strcpy_x(titleLogFont.lfFaceName, _countof(titleLogFont.lfFaceName), _T("Verdana Bold"));
+               INT titleFontPointSize = 12;
+               titleLogFont.lfHeight = -::MulDiv(titleFontPointSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72);
+               m_fontExteriorPageTitle.CreateFontIndirect(&titleLogFont);
+
+               // The Wizard 97 Spec recommends to do Bullets by having
+               // static text of "h" in the Marlett font.
+               bulletLogFont.lfCharSet = DEFAULT_CHARSET;
+               bulletLogFont.lfWeight = FW_NORMAL;
+               SecureHelper::strcpy_x(bulletLogFont.lfFaceName, _countof(bulletLogFont.lfFaceName), _T("Marlett"));
+               INT bulletFontSize = 8;
+               bulletLogFont.lfHeight = -::MulDiv(bulletFontSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72);
+               m_fontBullet.CreateFontIndirect(&bulletLogFont);
+       }
+
+// Message Handling
+       BEGIN_MSG_MAP(thisClass)
+               MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont(), OnGetExteriorPageTitleFont)
+               MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetBulletFont(), OnGetBulletFont)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnGetExteriorPageTitleFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return (LRESULT)(HFONT)m_fontExteriorPageTitle;
+       }
+
+       LRESULT OnGetBulletFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return (LRESULT)(HFONT)m_fontBullet;
+       }
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(!m_bReceivedFirstSizeMessage)
+               {
+                       m_bReceivedFirstSizeMessage = true;
+                       this->CenterWindow();
+               }
+
+               bHandled = FALSE;
+               return 0;
+       }
+};
+
+// for non-customized sheets
+class CWizard97Sheet : public CWizard97SheetImpl<CWizard97Sheet>
+{
+protected:
+// Typedefs
+       typedef CWizard97Sheet thisClass;
+       typedef CWizard97SheetImpl<CWizard97Sheet> baseClass;
+
+public:
+       CWizard97Sheet(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) :
+               baseClass(title, headerBitmap, watermarkBitmap, uStartPage, hWndParent)
+       { }
+
+       BEGIN_MSG_MAP(thisClass)
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CWizard97PageWindow - client side for a Wizard 97 style wizard page
+
+#define WIZARD97_EXTERIOR_CXDLG 317
+#define WIZARD97_EXTERIOR_CYDLG 193
+
+#define WIZARD97_INTERIOR_CXDLG 317
+#define WIZARD97_INTERIOR_CYDLG 143
+
+class CWizard97PageWindow : public CPropertyPageWindow
+{
+public:
+// Constructors
+       CWizard97PageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd)
+       { }
+
+       CWizard97PageWindow& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Attributes
+       CWizard97SheetWindow GetPropertySheet() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CWizard97SheetWindow(GetParent());
+       }
+
+// Operations
+       HFONT GetExteriorPageTitleFont(void)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return GetPropertySheet().GetExteriorPageTitleFont();
+       }
+
+       HFONT GetBulletFont(void)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return GetPropertySheet().GetBulletFont();
+       }
+
+// Implementation - overrides to prevent usage
+       HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
+       {
+               ATLASSERT(FALSE);
+               return NULL;
+       }
+
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CWizard97PageImpl - implements a Wizard 97 style wizard page
+
+template <class T, class TBase = CWizard97PageWindow>
+class ATL_NO_VTABLE CWizard97PageImpl : public CPropertyPageImpl< T, TBase >
+{
+protected:
+// Typedefs
+       typedef CWizard97PageImpl< T, TBase > thisClass;
+       typedef CPropertyPageImpl< T, TBase > baseClass;
+
+public:
+       CWizard97PageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
+       { }
+
+// Message Handling
+       BEGIN_MSG_MAP(thisClass)
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CWizard97ExteriorPageImpl - implements a Wizard 97 style exterior wizard page
+
+template <class T, class TBase = CWizard97PageWindow>
+class ATL_NO_VTABLE CWizard97ExteriorPageImpl : public CPropertyPageImpl< T, TBase >
+{
+protected:
+// Typedefs
+       typedef CWizard97ExteriorPageImpl< T, TBase > thisClass;
+       typedef CPropertyPageImpl< T, TBase > baseClass;
+
+public:
+// Constructors
+       CWizard97ExteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
+       {
+               m_psp.dwFlags |= PSP_HASHELP;
+               m_psp.dwFlags |= PSP_HIDEHEADER;
+       }
+
+// Message Handling
+       BEGIN_MSG_MAP(thisClass)
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CWizard97InteriorPageImpl - implements a Wizard 97 style interior wizard page
+
+template <class T, class TBase = CWizard97PageWindow>
+class ATL_NO_VTABLE CWizard97InteriorPageImpl : public CPropertyPageImpl< T, TBase >
+{
+protected:
+// Typedefs
+       typedef CWizard97InteriorPageImpl< T, TBase > thisClass;
+       typedef CPropertyPageImpl< T, TBase > baseClass;
+
+public:
+// Constructors
+       CWizard97InteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
+       {
+               m_psp.dwFlags |= PSP_HASHELP;
+               m_psp.dwFlags &= ~PSP_HIDEHEADER;
+               m_psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
+
+               // Be sure to have the derived class define this in the constructor.
+               // We'll default it to something obvious in case its forgotten.
+               baseClass::SetHeaderTitle(_T("Call SetHeaderTitle in Derived Class"));
+               baseClass::SetHeaderSubTitle(_T("Call SetHeaderSubTitle in the constructor of the Derived Class."));
+       }
+
+// Message Handling
+       BEGIN_MSG_MAP(thisClass)
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+};
+
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Aero Wizard support
+
+#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroWizardFrameWindow - client side for an Aero Wizard frame window
+
+class CAeroWizardFrameWindow : public CPropertySheetWindow
+{
+public:
+// Constructors
+       CAeroWizardFrameWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd)
+       { }
+
+       CAeroWizardFrameWindow& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Operations - new, Aero Wizard only
+       void SetNextText(LPCWSTR lpszText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_SETNEXTTEXT, 0, (LPARAM)lpszText);
+       }
+
+       void ShowWizardButtons(DWORD dwButtons, DWORD dwStates)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::PostMessage(m_hWnd, PSM_SHOWWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons);
+       }
+
+       void EnableWizardButtons(DWORD dwButtons, DWORD dwStates)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::PostMessage(m_hWnd, PSM_ENABLEWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons);
+       }
+
+       void SetButtonText(DWORD dwButton, LPCWSTR lpszText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, PSM_SETBUTTONTEXT, (WPARAM)dwButton, (LPARAM)lpszText);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroWizardFrameImpl - implements an Aero Wizard frame
+
+template <class T, class TBase = CAeroWizardFrameWindow>
+class ATL_NO_VTABLE CAeroWizardFrameImpl : public CPropertySheetImpl<T, TBase >
+{
+public:
+// Constructor
+       CAeroWizardFrameImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) :
+               CPropertySheetImpl<T, TBase >(title, uStartPage, hWndParent)
+       {
+               m_psh.dwFlags |= PSH_WIZARD | PSH_AEROWIZARD;
+       }
+
+// Operations
+       void EnableResizing()
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+               m_psh.dwFlags |= PSH_RESIZABLE;
+       }
+
+       void UseHeaderBitmap()
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+               m_psh.dwFlags |= PSH_HEADERBITMAP;
+       }
+
+       void SetNoMargin()
+       {
+               ATLASSERT(m_hWnd == NULL);   // can't do this after it's created
+               m_psh.dwFlags |= PSH_NOMARGIN;
+       }
+
+// Override to prevent use
+       HWND Create(HWND /*hWndParent*/ = NULL)
+       {
+               ATLASSERT(FALSE);   // not supported for Aero Wizard
+               return NULL;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroWizardFrame - for non-customized frames
+
+class CAeroWizardFrame : public CAeroWizardFrameImpl<CAeroWizardFrame>
+{
+public:
+       CAeroWizardFrame(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
+               : CAeroWizardFrameImpl<CAeroWizardFrame>(title, uStartPage, hWndParent)
+       { }
+
+       BEGIN_MSG_MAP(CAeroWizardFrame)
+               MESSAGE_HANDLER(WM_COMMAND, CAeroWizardFrameImpl<CAeroWizardFrame>::OnCommand)
+       END_MSG_MAP()
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroWizardPageWindow - client side for an Aero Wizard page
+
+class CAeroWizardPageWindow : public CPropertyPageWindow
+{
+public:
+// Constructors
+       CAeroWizardPageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd)
+       { }
+
+       CAeroWizardPageWindow& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Attributes
+       CAeroWizardFrameWindow GetAeroWizardFrame() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               // This is not really top-level frame window, but it processes all frame messages
+               return CAeroWizardFrameWindow(GetParent());
+       }
+
+// Operations - new, Aero Wizard only
+       void SetNextText(LPCWSTR lpszText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetAeroWizardFrame().SetNextText(lpszText);
+       }
+
+       void ShowWizardButtons(DWORD dwButtons, DWORD dwStates)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetAeroWizardFrame().ShowWizardButtons(dwButtons, dwStates);
+       }
+
+       void EnableWizardButtons(DWORD dwButtons, DWORD dwStates)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetAeroWizardFrame().EnableWizardButtons(dwButtons, dwStates);
+       }
+
+       void SetButtonText(DWORD dwButton, LPCWSTR lpszText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(GetParent() != NULL);
+               GetAeroWizardFrame().SetButtonText(dwButton, lpszText);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroWizardPageImpl - implements an Aero Wizard page
+
+template <class T, class TBase = CAeroWizardPageWindow>
+class ATL_NO_VTABLE CAeroWizardPageImpl : public CPropertyPageImpl<T, TBase >
+{
+public:
+       CAeroWizardPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<T, TBase >(title)
+       { }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroWizardPage - for non-customized pages
+
+template <WORD t_wDlgTemplateID>
+class CAeroWizardPage : public CAeroWizardPageImpl<CAeroWizardPage<t_wDlgTemplateID> >
+{
+public:
+       enum { IDD = t_wDlgTemplateID };
+
+       CAeroWizardPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardPageImpl<CAeroWizardPage>(title)
+       { }
+
+       DECLARE_EMPTY_MSG_MAP()
+};
+
+
+#ifndef _ATL_NO_HOSTING
+
+// Note: You must #include <atlhost.h> to use these classes
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroWizardAxPageImpl - Aero Wizard page that hosts ActiveX controls
+
+template <class T, class TBase = CAeroWizardPageWindow>
+class ATL_NO_VTABLE CAeroWizardAxPageImpl : public CAxPropertyPageImpl< T, TBase >
+{
+public:
+       CAeroWizardAxPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl< T, TBase >(title)
+       { }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroWizardAxPage - for non-customized pages
+
+template <WORD t_wDlgTemplateID>
+class CAeroWizardAxPage : public CAeroWizardAxPageImpl<CAeroWizardAxPage<t_wDlgTemplateID> >
+{
+public:
+       enum { IDD = t_wDlgTemplateID };
+
+       CAeroWizardAxPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardAxPageImpl<CAeroWizardAxPage>(title)
+       { }
+
+#if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)
+       // not empty so we handle accelerators/create controls
+       BEGIN_MSG_MAP(CAeroWizardAxPage)
+               CHAIN_MSG_MAP(CAeroWizardAxPageImpl<CAeroWizardAxPage<t_wDlgTemplateID> >)
+       END_MSG_MAP()
+#else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
+       DECLARE_EMPTY_MSG_MAP()
+#endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
+};
+
+#endif // _ATL_NO_HOSTING
+
+#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// TaskDialog support
+
+#if ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE)
+
+///////////////////////////////////////////////////////////////////////////////
+// AtlTaskDialog - support for TaskDialog() function
+
+inline int AtlTaskDialog(HWND hWndParent, 
+                         ATL::_U_STRINGorID WindowTitle, ATL::_U_STRINGorID MainInstructionText, ATL::_U_STRINGorID ContentText, 
+                         TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons = 0U, ATL::_U_STRINGorID Icon = (LPCTSTR)NULL)
+{
+       int nRet = -1;
+
+#ifdef _WTL_TASKDIALOG_DIRECT
+       USES_CONVERSION;
+       HRESULT hRet = ::TaskDialog(hWndParent, ModuleHelper::GetResourceInstance(), 
+               IS_INTRESOURCE(WindowTitle.m_lpstr) ? (LPCWSTR) WindowTitle.m_lpstr : T2CW(WindowTitle.m_lpstr), 
+               IS_INTRESOURCE(MainInstructionText.m_lpstr) ? (LPCWSTR) MainInstructionText.m_lpstr : T2CW(MainInstructionText.m_lpstr), 
+               IS_INTRESOURCE(ContentText.m_lpstr) ?  (LPCWSTR) ContentText.m_lpstr : T2CW(ContentText.m_lpstr), 
+               dwCommonButtons, 
+               IS_INTRESOURCE(Icon.m_lpstr) ? (LPCWSTR) Icon.m_lpstr : T2CW(Icon.m_lpstr),
+               &nRet);
+       ATLVERIFY(SUCCEEDED(hRet));
+#else
+       // This allows apps to run on older versions of Windows
+       typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialog)(HWND hwndParent, HINSTANCE hInstance, PCWSTR pszWindowTitle, PCWSTR pszMainInstruction, PCWSTR pszContent, TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons, PCWSTR pszIcon, int* pnButton);
+
+       HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
+       if(m_hCommCtrlDLL != NULL)
+       {
+               PFN_TaskDialog pfnTaskDialog = (PFN_TaskDialog)::GetProcAddress(m_hCommCtrlDLL, "TaskDialog");
+               if(pfnTaskDialog != NULL)
+               {
+                       USES_CONVERSION;
+                       HRESULT hRet = pfnTaskDialog(hWndParent, ModuleHelper::GetResourceInstance(), 
+                               IS_INTRESOURCE(WindowTitle.m_lpstr) ? (LPCWSTR) WindowTitle.m_lpstr : T2CW(WindowTitle.m_lpstr), 
+                               IS_INTRESOURCE(MainInstructionText.m_lpstr) ? (LPCWSTR) MainInstructionText.m_lpstr : T2CW(MainInstructionText.m_lpstr), 
+                               IS_INTRESOURCE(ContentText.m_lpstr) ?  (LPCWSTR) ContentText.m_lpstr : T2CW(ContentText.m_lpstr), 
+                               dwCommonButtons, 
+                               IS_INTRESOURCE(Icon.m_lpstr) ? (LPCWSTR) Icon.m_lpstr : T2CW(Icon.m_lpstr),
+                               &nRet);
+                       ATLVERIFY(SUCCEEDED(hRet));
+               }
+
+               ::FreeLibrary(m_hCommCtrlDLL);
+       }
+#endif
+
+       return nRet;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTaskDialogConfig - TASKDIALOGCONFIG wrapper
+
+class CTaskDialogConfig : public TASKDIALOGCONFIG
+{
+public:
+// Constructor
+       CTaskDialogConfig()
+       {
+               Init();
+       }
+
+       void Init()
+       {
+               memset(this, 0, sizeof(TASKDIALOGCONFIG));   // initialize structure to 0/NULL
+               this->cbSize = sizeof(TASKDIALOGCONFIG);
+               this->hInstance = ModuleHelper::GetResourceInstance();
+       }
+
+// Operations - setting values
+       // common buttons
+       void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons)
+       {
+               this->dwCommonButtons = dwCommonButtons;
+       }
+
+       // window title text
+       void SetWindowTitle(UINT nID)
+       {
+               this->pszWindowTitle = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetWindowTitle(LPCWSTR lpstrWindowTitle)
+       {
+               this->pszWindowTitle = lpstrWindowTitle;
+       }
+
+       // main icon
+       void SetMainIcon(HICON hIcon)
+       {
+               this->dwFlags |= TDF_USE_HICON_MAIN;
+               this->hMainIcon = hIcon;
+       }
+
+       void SetMainIcon(UINT nID)
+       {
+               this->dwFlags &= ~TDF_USE_HICON_MAIN;
+               this->pszMainIcon = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetMainIcon(LPCWSTR lpstrMainIcon)
+       {
+               this->dwFlags &= ~TDF_USE_HICON_MAIN;
+               this->pszMainIcon = lpstrMainIcon;
+       }
+
+       // main instruction text
+       void SetMainInstructionText(UINT nID)
+       {
+               this->pszMainInstruction = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetMainInstructionText(LPCWSTR lpstrMainInstruction)
+       {
+               this->pszMainInstruction = lpstrMainInstruction;
+       }
+
+       // content text
+       void SetContentText(UINT nID)
+       {
+               this->pszContent = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetContentText(LPCWSTR lpstrContent)
+       {
+               this->pszContent = lpstrContent;
+       }
+
+       // buttons
+       void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0)
+       {
+               this->pButtons = pButtons;
+               this->cButtons = cButtons;
+               if(nDefaultButton != 0)
+                       this->nDefaultButton = nDefaultButton;
+       }
+
+       void SetDefaultButton(int nDefaultButton)
+       {
+               this->nDefaultButton = nDefaultButton;
+       }
+
+       // radio buttons
+       void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0)
+       {
+               this->pRadioButtons = pRadioButtons;
+               this->cRadioButtons = cRadioButtons;
+               if(nDefaultRadioButton != 0)
+                       this->nDefaultRadioButton = nDefaultRadioButton;
+       }
+
+       void SetDefaultRadioButton(int nDefaultRadioButton)
+       {
+               this->nDefaultRadioButton = nDefaultRadioButton;
+       }
+
+       // verification text
+       void SetVerificationText(UINT nID)
+       {
+               this->pszVerificationText = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetVerificationText(LPCWSTR lpstrVerificationText)
+       {
+               this->pszVerificationText = lpstrVerificationText;
+       }
+
+       // expanded information text
+       void SetExpandedInformationText(UINT nID)
+       {
+               this->pszExpandedInformation = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation)
+       {
+               this->pszExpandedInformation = lpstrExpandedInformation;
+       }
+
+       // expanded control text
+       void SetExpandedControlText(UINT nID)
+       {
+               this->pszExpandedControlText = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetExpandedControlText(LPCWSTR lpstrExpandedControlText)
+       {
+               this->pszExpandedControlText = lpstrExpandedControlText;
+       }
+
+       // collapsed control text
+       void SetCollapsedControlText(UINT nID)
+       {
+               this->pszCollapsedControlText = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText)
+       {
+               this->pszCollapsedControlText = lpstrCollapsedControlText;
+       }
+
+       // footer icon
+       void SetFooterIcon(HICON hIcon)
+       {
+               this->dwFlags |= TDF_USE_HICON_FOOTER;
+               this->hFooterIcon = hIcon;
+       }
+
+       void SetFooterIcon(UINT nID)
+       {
+               this->dwFlags &= ~TDF_USE_HICON_FOOTER;
+               this->pszFooterIcon = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetFooterIcon(LPCWSTR lpstrFooterIcon)
+       {
+               this->dwFlags &= ~TDF_USE_HICON_FOOTER;
+               this->pszFooterIcon = lpstrFooterIcon;
+       }
+
+       // footer text
+       void SetFooterText(UINT nID)
+       {
+               this->pszFooter = MAKEINTRESOURCEW(nID);
+       }
+
+       void SetFooterText(LPCWSTR lpstrFooterText)
+       {
+               this->pszFooter = lpstrFooterText;
+       }
+
+       // width (in DLUs)
+       void SetWidth(UINT cxWidth)
+       {
+               this->cxWidth = cxWidth;
+       }
+
+       // modify flags
+       void ModifyFlags(DWORD dwRemove, DWORD dwAdd)
+       {
+               this->dwFlags = (this->dwFlags & ~dwRemove) | dwAdd;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTaskDialogImpl - implements a Task Dialog
+
+template <class T>
+class ATL_NO_VTABLE CTaskDialogImpl
+{
+public:
+       CTaskDialogConfig m_tdc;
+       HWND m_hWnd;   // used only in callback functions
+
+// Constructor
+       CTaskDialogImpl(HWND hWndParent = NULL) : m_hWnd(NULL)
+       {
+               m_tdc.hwndParent = hWndParent;
+               m_tdc.pfCallback = T::TaskDialogCallback;
+               m_tdc.lpCallbackData = (LONG_PTR)static_cast<T*>(this);
+       }
+
+// Operations
+       HRESULT DoModal(HWND hWndParent = ::GetActiveWindow(), int* pnButton = NULL, int* pnRadioButton = NULL, BOOL* pfVerificationFlagChecked = NULL)
+       {
+               if(m_tdc.hwndParent == NULL)
+                       m_tdc.hwndParent = hWndParent;
+
+#ifdef _WTL_TASKDIALOG_DIRECT
+               return ::TaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked);
+#else
+
+               // This allows apps to run on older versions of Windows
+               typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialogIndirect)(const TASKDIALOGCONFIG* pTaskConfig, int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked);
+
+               HRESULT hRet = E_UNEXPECTED;
+               HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
+               if(m_hCommCtrlDLL != NULL)
+               {
+                       PFN_TaskDialogIndirect pfnTaskDialogIndirect = (PFN_TaskDialogIndirect)::GetProcAddress(m_hCommCtrlDLL, "TaskDialogIndirect");
+                       if(pfnTaskDialogIndirect != NULL)
+                               hRet = pfnTaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked);
+
+                       ::FreeLibrary(m_hCommCtrlDLL);
+               }
+
+               return hRet;
+#endif
+       }
+
+// Operations - setting values of TASKDIALOGCONFIG
+       // common buttons
+       void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons)
+       {       m_tdc.SetCommonButtons(dwCommonButtons); }
+       // window title text
+       void SetWindowTitle(UINT nID)
+       {       m_tdc.SetWindowTitle(nID); }
+       void SetWindowTitle(LPCWSTR lpstrWindowTitle)
+       {       m_tdc.SetWindowTitle(lpstrWindowTitle); }
+       // main icon
+       void SetMainIcon(HICON hIcon)
+       {       m_tdc.SetMainIcon(hIcon); }
+       void SetMainIcon(UINT nID)
+       {       m_tdc.SetMainIcon(nID); }
+       void SetMainIcon(LPCWSTR lpstrMainIcon)
+       {       m_tdc.SetMainIcon(lpstrMainIcon); }
+       // main instruction text
+       void SetMainInstructionText(UINT nID)
+       {       m_tdc.SetMainInstructionText(nID); }
+       void SetMainInstructionText(LPCWSTR lpstrMainInstruction)
+       {       m_tdc.SetMainInstructionText(lpstrMainInstruction); }
+       // content text
+       void SetContentText(UINT nID)
+       {       m_tdc.SetContentText(nID); }
+       void SetContentText(LPCWSTR lpstrContent)
+       {       m_tdc.SetContentText(lpstrContent); }
+       // buttons
+       void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0)
+       {       m_tdc.SetButtons(pButtons, cButtons, nDefaultButton); }
+       void SetDefaultButton(int nDefaultButton)
+       {       m_tdc.SetDefaultButton(nDefaultButton); }
+       // radio buttons
+       void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0)
+       {       m_tdc.SetRadioButtons(pRadioButtons, cRadioButtons, nDefaultRadioButton); }
+       void SetDefaultRadioButton(int nDefaultRadioButton)
+       {       m_tdc.SetDefaultRadioButton(nDefaultRadioButton); }
+       // verification text
+       void SetVerificationText(UINT nID)
+       {       m_tdc.SetVerificationText(nID); }
+       void SetVerificationText(LPCWSTR lpstrVerificationText)
+       {       m_tdc.SetVerificationText(lpstrVerificationText); }
+       // expanded information text
+       void SetExpandedInformationText(UINT nID)
+       {       m_tdc.SetExpandedInformationText(nID); }
+       void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation)
+       {       m_tdc.SetExpandedInformationText(lpstrExpandedInformation); }
+       // expanded control text
+       void SetExpandedControlText(UINT nID)
+       {       m_tdc.SetExpandedControlText(nID); }
+       void SetExpandedControlText(LPCWSTR lpstrExpandedControlText)
+       {       m_tdc.SetExpandedControlText(lpstrExpandedControlText); }
+       // collapsed control text
+       void SetCollapsedControlText(UINT nID)
+       {       m_tdc.SetCollapsedControlText(nID); }
+       void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText)
+       {       m_tdc.SetCollapsedControlText(lpstrCollapsedControlText); }
+       // footer icon
+       void SetFooterIcon(HICON hIcon)
+       {       m_tdc.SetFooterIcon(hIcon); }
+       void SetFooterIcon(UINT nID)
+       {       m_tdc.SetFooterIcon(nID); }
+       void SetFooterIcon(LPCWSTR lpstrFooterIcon)
+       {       m_tdc.SetFooterIcon(lpstrFooterIcon); }
+       // footer text
+       void SetFooterText(UINT nID)
+       {       m_tdc.SetFooterText(nID); }
+       void SetFooterText(LPCWSTR lpstrFooterText)
+       {       m_tdc.SetFooterText(lpstrFooterText); }
+       // width (in DLUs)
+       void SetWidth(UINT cxWidth)
+       {       m_tdc.SetWidth(cxWidth); }
+       // modify flags
+       void ModifyFlags(DWORD dwRemove, DWORD dwAdd)
+       {       m_tdc.ModifyFlags(dwRemove, dwAdd); }
+
+// Implementation
+       static HRESULT CALLBACK TaskDialogCallback(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData)
+       {
+               T* pT = (T*)lpRefData;
+               ATLASSERT(pT->m_hWnd == NULL || pT->m_hWnd == hWnd);
+
+               BOOL bRet = FALSE;
+               switch(uMsg)
+               {
+               case TDN_DIALOG_CONSTRUCTED:
+                       pT->m_hWnd = hWnd;
+                       pT->OnDialogConstructed();
+                       break;
+               case TDN_CREATED:
+                       pT->OnCreated();
+                       break;
+               case TDN_BUTTON_CLICKED:
+                       bRet = pT->OnButtonClicked((int)wParam);
+                       break;
+               case TDN_RADIO_BUTTON_CLICKED:
+                       pT->OnRadioButtonClicked((int)wParam);
+                       break;
+               case TDN_HYPERLINK_CLICKED:
+                       pT->OnHyperlinkClicked((LPCWSTR)lParam);
+                       break;
+               case TDN_EXPANDO_BUTTON_CLICKED:
+                       pT->OnExpandoButtonClicked((wParam != 0));
+                       break;
+               case TDN_VERIFICATION_CLICKED:
+                       pT->OnVerificationClicked((wParam != 0));
+                       break;
+               case TDN_HELP:
+                       pT->OnHelp();
+                       break;
+               case TDN_TIMER:
+                       bRet = pT->OnTimer((DWORD)wParam);
+                       break;
+               case TDN_NAVIGATED:
+                       pT->OnNavigated();
+                       break;
+               case TDN_DESTROYED:
+                       pT->OnDestroyed();
+                       pT->m_hWnd = NULL;
+                       break;
+               default:
+                       ATLTRACE2(atlTraceUI, 0, _T("Unknown notification received in CTaskDialogImpl::TaskDialogCallback\n"));
+                       break;
+               }
+
+               return (HRESULT)bRet;
+       }
+
+// Overrideables - notification handlers
+       void OnDialogConstructed()
+       {
+       }
+
+       void OnCreated()
+       {
+       }
+
+       BOOL OnButtonClicked(int /*nButton*/)
+       {
+               return FALSE;   // don't prevent dialog to close
+       }
+
+       void OnRadioButtonClicked(int /*nRadioButton*/)
+       {
+       }
+
+       void OnHyperlinkClicked(LPCWSTR /*pszHREF*/)
+       {
+       }
+
+       void OnExpandoButtonClicked(bool /*bExpanded*/)
+       {
+       }
+
+       void OnVerificationClicked(bool /*bChecked*/)
+       {
+       }
+
+       void OnHelp()
+       {
+       }
+
+       BOOL OnTimer(DWORD /*dwTickCount*/)
+       {
+               return FALSE;   // don't reset counter
+       }
+
+       void OnNavigated()
+       {
+       }
+
+       void OnDestroyed()
+       {
+       }
+
+// Commands - valid to call only from handlers
+       void NavigatePage(TASKDIALOGCONFIG& tdc)
+       {
+               ATLASSERT(m_hWnd != NULL);
+
+               tdc.cbSize = sizeof(TASKDIALOGCONFIG);
+               if(tdc.hwndParent == NULL)
+                       tdc.hwndParent = m_tdc.hwndParent;
+               tdc.pfCallback = m_tdc.pfCallback;
+               tdc.lpCallbackData = m_tdc.lpCallbackData;
+               (TASKDIALOGCONFIG)m_tdc = tdc;
+
+               ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&tdc);
+       }
+
+       // modify TASKDIALOGCONFIG values, then call this to update task dialog
+       void NavigatePage()
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&m_tdc);
+       }
+
+       void ClickButton(int nButton)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_CLICK_BUTTON, nButton, 0L);
+       }
+
+       void SetMarqueeProgressBar(BOOL bMarquee)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_SET_MARQUEE_PROGRESS_BAR, bMarquee, 0L);
+       }
+
+       BOOL SetProgressBarState(int nNewState)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_STATE, nNewState, 0L);
+       }
+
+       DWORD SetProgressBarRange(int nMinRange, int nMaxRange)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               return (DWORD)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(nMinRange, nMaxRange));
+       }
+
+       int SetProgressBarPos(int nNewPos)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               return (int)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_POS, nNewPos, 0L);
+       }
+
+       BOOL SetProgressBarMarquee(BOOL bMarquee, UINT uSpeed)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_MARQUEE, bMarquee, uSpeed);
+       }
+
+       void SetElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_SET_ELEMENT_TEXT, element, (LPARAM)lpstrText);
+       }
+
+       void ClickRadioButton(int nRadioButton)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_CLICK_RADIO_BUTTON, nRadioButton, 0L);
+       }
+
+       void EnableButton(int nButton, BOOL bEnable)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_ENABLE_BUTTON, nButton, bEnable);
+       }
+
+       void EnableRadioButton(int nButton, BOOL bEnable)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_ENABLE_RADIO_BUTTON, nButton, bEnable);
+       }
+
+       void ClickVerification(BOOL bCheck, BOOL bFocus)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_CLICK_VERIFICATION, bCheck, bFocus);
+       }
+
+       void UpdateElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_UPDATE_ELEMENT_TEXT, element, (LPARAM)lpstrText);
+       }
+
+       void SetButtonElevationRequiredState(int nButton, BOOL bElevation)
+       {
+               ATLASSERT(m_hWnd != NULL);
+               ::SendMessage(m_hWnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, nButton, bElevation);
+       }
+
+       void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, HICON hIcon)
+       {
+               ATLASSERT(m_hWnd != NULL);
+#ifdef _DEBUG
+               if(element == TDIE_ICON_MAIN)
+                       ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) != 0);
+               else if(element == TDIE_ICON_FOOTER)
+                       ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) != 0);
+#endif // _DEBUG
+               ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)hIcon);
+       }
+
+       void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, LPCWSTR lpstrIcon)
+       {
+               ATLASSERT(m_hWnd != NULL);
+#ifdef _DEBUG
+               if(element == TDIE_ICON_MAIN)
+                       ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) == 0);
+               else if(element == TDIE_ICON_FOOTER)
+                       ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) == 0);
+#endif // _DEBUG
+               ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)lpstrIcon);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTaskDialog - for non-customized task dialogs
+
+class CTaskDialog : public CTaskDialogImpl<CTaskDialog>
+{
+public:
+       CTaskDialog(HWND hWndParent = NULL) : CTaskDialogImpl<CTaskDialog>(hWndParent)
+       {
+               m_tdc.pfCallback = NULL;
+       }
+};
+
+#endif // ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE)
+
+}; // namespace WTL
+
+#endif // __ATLDLGS_H__
diff --git a/include/WTL/Include/atldwm.h b/include/WTL/Include/atldwm.h
new file mode 100644 (file)
index 0000000..5f4bf1f
--- /dev/null
@@ -0,0 +1,465 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLDWM_H__
+#define __ATLDWM_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifdef _WIN32_WCE
+       #error atldwm.h is not supported on Windows CE
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atldwm.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atldwm.h requires atlwin.h to be included first
+#endif
+
+#if (_WIN32_WINNT < 0x0600)
+       #error atldwm.h requires _WIN32_WINNT >= 0x0600
+#endif // (_WIN32_WINNT < 0x0600)
+
+#ifndef _DWMAPI_H_
+#include <dwmapi.h>
+#endif // _DWMAPI_H_
+#pragma comment(lib, "dwmapi.lib")
+
+// Note: To create an application that also runs on older versions of Windows,
+// use delay load of dwmapi.dll and ensure that no calls to the DWM API are
+// Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib, 
+// and add dwmapi.dll in the Linker.Input.Delay Loaded DLLs section of the 
+// project properties.
+#if (_MSC_VER < 1300) && !defined(_WTL_NO_DWMAPI_DELAYLOAD)
+       #pragma comment(lib, "delayimp.lib")
+       #pragma comment(linker, "/delayload:dwmapi.dll")
+#endif // (_MSC_VER < 1300) && !defined(_WTL_NO_DWMAPI_DELAYLOAD)
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CDwm
+// CDwmImpl<T, TBase>
+// CDwmWindowT<TBase> - CDwmWindow
+// CDwmThumbnailT<t_bManaged, TBase>
+// CDwmThumbnail
+// CDwmThumbnailHandle
+// CAeroControlImpl
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CDwm - wrapper for DWM handle
+
+class CDwm
+{
+public:
+// Data members
+       static int m_nIsDwmSupported;
+
+// Constructor
+       CDwm()
+       {
+               IsDwmSupported();
+       }
+
+// Dwm support helper
+       static bool IsDwmSupported()
+       {
+               if(m_nIsDwmSupported == -1)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDwm::IsDwmSupported.\n"));
+                               ATLASSERT(FALSE);
+                               return false;
+                       }
+
+                       if(m_nIsDwmSupported == -1)
+                       {
+                               HMODULE hDwmDLL = ::LoadLibrary(_T("dwmapi.dll"));
+                               m_nIsDwmSupported = (hDwmDLL != NULL) ? 1 : 0;
+                               if(hDwmDLL != NULL)
+                                       ::FreeLibrary(hDwmDLL);
+                       }
+
+                       lock.Unlock();
+               }
+
+               ATLASSERT(m_nIsDwmSupported != -1);
+               return (m_nIsDwmSupported == 1);
+       }
+
+// Operations
+       BOOL DwmIsCompositionEnabled() const
+       {
+               if(!IsDwmSupported()) return FALSE;
+               BOOL bRes = FALSE;
+               return SUCCEEDED(::DwmIsCompositionEnabled(&bRes)) && bRes;
+       }
+
+       BOOL DwmEnableComposition(UINT fEnable)
+       {
+               if(!IsDwmSupported()) return FALSE;
+               return SUCCEEDED(::DwmEnableComposition(fEnable));
+       }
+
+       BOOL DwmEnableMMCSS(BOOL fEnableMMCSS)
+       {
+               if(!IsDwmSupported()) return FALSE;
+               return SUCCEEDED(::DwmEnableMMCSS(fEnableMMCSS));
+       }
+
+       HRESULT DwmGetColorizationColor(DWORD* pcrColorization, BOOL* pfOpaqueBlend)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               return ::DwmGetColorizationColor(pcrColorization, pfOpaqueBlend);
+       }
+
+       HRESULT DwmFlush()
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               return ::DwmFlush();
+       }
+};
+
+__declspec(selectany) int CDwm::m_nIsDwmSupported = -1;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDwmImpl - DWM window support
+
+template <class T, class TBase = CDwm>
+class CDwmImpl : public TBase
+{
+public:
+       HRESULT DwmEnableBlurBehindWindow(const DWM_BLURBEHIND* pBB)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmEnableBlurBehindWindow(pT->m_hWnd, pBB);
+       }
+
+       HRESULT DwmExtendFrameIntoClientArea(const MARGINS* pMargins)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmExtendFrameIntoClientArea(pT->m_hWnd, pMargins);
+       }
+
+       HRESULT DwmExtendFrameIntoEntireClientArea()
+       {
+               MARGINS margins = { -1 };
+               return DwmExtendFrameIntoClientArea(&margins);
+       }
+
+       HRESULT DwmGetCompositionTimingInfo(DWM_TIMING_INFO* pTimingInfo)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmGetCompositionTimingInfo(pT->m_hWnd, pTimingInfo);
+       }
+
+       HRESULT DwmGetWindowAttribute(DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmGetWindowAttribute(pT->m_hWnd, dwAttribute, pvAttribute, cbAttribute);
+       }
+
+       HRESULT DwmModifyPreviousDxFrameDuration(INT cRefreshes, BOOL fRelative)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmModifyPreviousDxFrameDuration(pT->m_hWnd, cRefreshes, fRelative);
+       }
+
+       HRESULT DwmSetDxFrameDuration(INT cRefreshes)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmSetDxFrameDuration(pT->m_hWnd, cRefreshes);
+       }
+
+       HRESULT DwmSetPresentParameters(DWM_PRESENT_PARAMETERS* pPresentParams)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmSetPresentParameters(pT->m_hWnd, pPresentParams);
+       }
+
+       HRESULT DwmSetWindowAttribute(DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmSetWindowAttribute(pT->m_hWnd, dwAttribute, pvAttribute, cbAttribute);
+       }
+
+       HRESULT DwmAttachMilContent()
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmAttachMilContent(pT->m_hWnd);
+       }
+
+       HRESULT DwmDetachMilContent()
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DwmDetachMilContent(pT->m_hWnd);
+       }
+};
+
+template <class TBase>
+class CDwmWindowT : public TBase, public CDwmImpl<CDwmWindowT< TBase > >
+{
+public:
+       CDwmWindowT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CDwmWindowT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+};
+
+typedef CDwmWindowT<ATL::CWindow>      CDwmWindow;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDwmThumbnail - provides DWM thumbnail support
+
+template <bool t_bManaged, class TBase = CDwm>
+class CDwmThumbnailT : public TBase
+{
+public:
+// Data members
+       HTHUMBNAIL m_hThumbnail;
+
+// Constructor
+       CDwmThumbnailT(HTHUMBNAIL hThumbnail = NULL) : m_hThumbnail(hThumbnail)
+       {
+       }
+
+       ~CDwmThumbnailT()
+       {
+               if(t_bManaged && m_hThumbnail != NULL)
+                       Unregister();
+       }
+
+// Operations
+       CDwmThumbnailT<t_bManaged, TBase>& operator =(HTHUMBNAIL hThumbnail)
+       {
+               Attach(hThumbnail);
+               return *this;
+       }
+
+       void Attach(HTHUMBNAIL hThumbnailNew)
+       {
+               if(t_bManaged && m_hThumbnail != NULL && m_hThumbnail != hThumbnailNew)
+                       Unregister();
+               m_hThumbnail = hThumbnailNew;
+       }
+
+       HTHUMBNAIL Detach()
+       {
+               HTHUMBNAIL hThumbnail = m_hThumbnail;
+               m_hThumbnail = NULL;
+               return hThumbnail;
+       }
+
+       HRESULT Register(HWND hwndDestination, HWND hwndSource)
+       {
+               ATLASSERT(::IsWindow(hwndDestination));
+               ATLASSERT(::IsWindow(hwndSource));
+               ATLASSERT(m_hThumbnail==NULL);
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               return ::DwmRegisterThumbnail(hwndDestination, hwndSource, &m_hThumbnail);
+       }
+
+       HRESULT Unregister()
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               if(m_hThumbnail == NULL) return S_FALSE;
+               HRESULT Hr = ::DwmUnregisterThumbnail(m_hThumbnail);
+               if(SUCCEEDED(Hr)) m_hThumbnail = NULL;
+               return Hr;
+       }
+
+       operator HTHUMBNAIL() const { return m_hThumbnail; }
+
+       bool IsNull() const { return (m_hThumbnail == NULL); }
+
+       HRESULT UpdateProperties(const DWM_THUMBNAIL_PROPERTIES* ptnProperties)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               ATLASSERT(m_hThumbnail != NULL);
+               return ::DwmUpdateThumbnailProperties(m_hThumbnail, ptnProperties);
+       }
+
+// Attributes
+       HRESULT QuerySourceSize(PSIZE pSize)
+       {
+               if(!IsDwmSupported()) return E_NOTIMPL;
+               ATLASSERT(m_hThumbnail != NULL);
+               return ::DwmQueryThumbnailSourceSize(m_hThumbnail, pSize);
+       }
+};
+
+typedef CDwmThumbnailT<true, CDwm> CDwmThumbnail;
+typedef CDwmThumbnailT<false, CDwm> CDwmThumbnailHandle;
+
+
+#ifdef __ATLTHEME_H__
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroControlImpl - Base class for controls on Glass
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class CAeroControlImpl :
+       public CThemeImpl<T>,
+       public CBufferedPaintImpl<T>,
+       public ATL::CWindowImpl<T, TBase, TWinTraits>
+{
+public:
+       typedef CThemeImpl<T> _themeClass;
+       typedef CBufferedPaintImpl<T> _baseClass;
+       typedef ATL::CWindowImpl<T, TBase, TWinTraits> _windowClass;
+
+       CAeroControlImpl()
+       {
+               m_PaintParams.dwFlags = BPPF_ERASE;
+       }
+
+       static LPCWSTR GetThemeName()
+       {
+#ifdef _UNICODE
+               return TBase::GetWndClassName();
+#else
+               ATLASSERT(!_T("Return UNICODE string of window classname / theme class"));
+               return NULL;
+#endif // _UNICODE
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CAeroControlImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
+               CHAIN_MSG_MAP(_themeClass)
+               CHAIN_MSG_MAP(_baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Init();
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(IsThemingSupported()) Invalidate(FALSE);
+               bHandled = FALSE;
+               return 0;
+       }
+
+// Operations
+       BOOL SubclassWindow(HWND hWnd)
+       {
+               ATLASSERT(m_hWnd == NULL);
+               ATLASSERT(::IsWindow(hWnd));
+               BOOL bRet = _windowClass::SubclassWindow(hWnd);
+               if(bRet) {
+                       T* pT = static_cast<T*>(this);
+                       pT->Init();
+               }
+               return bRet;
+       }
+
+// Implementation
+       LRESULT DefWindowProc()
+       {
+               const _ATL_MSG* pMsg = m_pCurrentMsg;
+               LRESULT lRes = 0;
+               if(pMsg != NULL)
+                       lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
+               return lRes;
+       }
+
+       LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               T* pT = static_cast<T*>(this);
+               LRESULT lRes = 0;
+               if( ::DwmDefWindowProc(pT->m_hWnd, uMsg, wParam, lParam, &lRes) ) return lRes;
+               return _windowClass::DefWindowProc(uMsg, wParam, lParam);
+       }
+
+       void DoBufferedPaint(HDC hDC, RECT& rcPaint)
+       {
+               T* pT = static_cast<T*>(this);
+               HDC hDCPaint = NULL;
+               RECT rcClient = { 0 };
+               GetClientRect(&rcClient);
+               m_BufferedPaint.Begin(hDC, &rcClient, m_dwFormat, &m_PaintParams, &hDCPaint);
+               ATLASSERT(hDCPaint != NULL);
+               pT->DoAeroPaint(hDCPaint, rcClient, rcPaint);
+               m_BufferedPaint.End();
+       }
+
+       void DoPaint(HDC /*hdc*/, RECT& /*rcClient*/)
+       {
+               DefWindowProc();
+       }
+
+// Overridables
+       void Init()
+       {
+               T* pT = static_cast<T*>(this);
+               SetThemeClassList(pT->GetThemeName());
+               if(m_lpstrThemeClassList != NULL)
+                       OpenThemeData();
+       }
+
+       void DoAeroPaint(HDC hDC, RECT& /*rcClient*/, RECT& rcPaint)
+       {
+               DefWindowProc(WM_PAINT, (WPARAM) hDC, 0L);
+               m_BufferedPaint.MakeOpaque(&rcPaint);
+       }
+};
+
+#endif // __ATLTHEME_H__
+
+
+}; // namespace WTL
+
+
+#endif // __ATLDWM_H__
diff --git a/include/WTL/Include/atlfind.h b/include/WTL/Include/atlfind.h
new file mode 100644 (file)
index 0000000..c4a47a4
--- /dev/null
@@ -0,0 +1,1036 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLFIND_H__
+#define __ATLFIND_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifdef _WIN32_WCE
+       #error atlfind.h is not supported on Windows CE
+#endif
+
+#ifndef __ATLCTRLS_H__
+       #error atlfind.h requires atlctrls.h to be included first
+#endif
+
+#ifndef __ATLDLGS_H__
+       #error atlfind.h requires atldlgs.h to be included first
+#endif
+
+#if !((defined(__ATLMISC_H__) && defined(_WTL_USE_CSTRING)) || defined(__ATLSTR_H__))
+       #error atlfind.h requires CString (either from ATL's atlstr.h or WTL's atlmisc.h with _WTL_USE_CSTRING)
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CEditFindReplaceImplBase<T, TFindReplaceDialog>
+// CEditFindReplaceImpl<T, TFindReplaceDialog>
+// CRichEditFindReplaceImpl<T, TFindReplaceDialog>
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CEditFindReplaceImplBase - Base class for mixin classes that
+// help implement Find/Replace for CEdit or CRichEditCtrl based window classes.
+
+template <class T, class TFindReplaceDialog = CFindReplaceDialog>
+class CEditFindReplaceImplBase
+{
+protected:
+// Typedefs
+       typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> thisClass;
+
+// Data members
+       TFindReplaceDialog* m_pFindReplaceDialog;
+       _CSTRING_NS::CString m_sFindNext, m_sReplaceWith;
+       BOOL m_bFindOnly, m_bFirstSearch, m_bMatchCase, m_bWholeWord, m_bFindDown;
+       LONG m_nInitialSearchPos;
+       HCURSOR m_hOldCursor;
+
+// Enumerations
+       enum TranslationTextItem
+       {
+               eText_OnReplaceAllMessage   = 0,
+               eText_OnReplaceAllTitle     = 1,
+               eText_OnTextNotFoundMessage = 2,
+               eText_OnTextNotFoundTitle   = 3
+       };
+
+public:
+// Constructors
+       CEditFindReplaceImplBase() :
+               m_pFindReplaceDialog(NULL),
+               m_bFindOnly(TRUE),
+               m_bFirstSearch(TRUE),
+               m_bMatchCase(FALSE),
+               m_bWholeWord(FALSE),
+               m_bFindDown(TRUE),
+               m_nInitialSearchPos(0),
+               m_hOldCursor(NULL)
+       {
+       }
+
+// Message Handlers
+       BEGIN_MSG_MAP(thisClass)
+       ALT_MSG_MAP(1)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_HANDLER(TFindReplaceDialog::GetFindReplaceMsg(), OnFindReplaceCmd)
+               COMMAND_ID_HANDLER(ID_EDIT_FIND, OnEditFind)
+               COMMAND_ID_HANDLER(ID_EDIT_REPEAT, OnEditRepeat)
+               COMMAND_ID_HANDLER(ID_EDIT_REPLACE, OnEditReplace)
+       END_MSG_MAP()
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_pFindReplaceDialog != NULL)
+               {
+                       m_pFindReplaceDialog->SendMessage(WM_CLOSE);
+                       ATLASSERT(m_pFindReplaceDialog == NULL);
+               }
+
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnFindReplaceCmd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+
+               TFindReplaceDialog* pDialog = TFindReplaceDialog::GetNotifier(lParam);
+               if(pDialog == NULL)
+               {
+                       ATLASSERT(FALSE);
+                       ::MessageBeep(MB_ICONERROR);
+                       return 1;
+               }
+               ATLASSERT(pDialog == m_pFindReplaceDialog);
+
+               LPFINDREPLACE findReplace = (LPFINDREPLACE)lParam;
+               if((m_pFindReplaceDialog != NULL) && (findReplace != NULL))
+               {
+                       if(pDialog->FindNext())
+                       {
+                               pT->OnFindNext(pDialog->GetFindString(), pDialog->SearchDown(),
+                                       pDialog->MatchCase(), pDialog->MatchWholeWord());
+                       }
+                       else if(pDialog->ReplaceCurrent())
+                       {
+                               pT->OnReplaceSel(pDialog->GetFindString(),
+                                       pDialog->SearchDown(), pDialog->MatchCase(), pDialog->MatchWholeWord(),
+                                       pDialog->GetReplaceString());
+                       }
+                       else if(pDialog->ReplaceAll())
+                       {
+                               pT->OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(),
+                                       pDialog->MatchCase(), pDialog->MatchWholeWord());
+                       }
+                       else if(pDialog->IsTerminating())
+                       {
+                               // Dialog is going away (but hasn't gone away yet)
+                               // OnFinalMessage will "delete this"
+                               pT->OnTerminatingFindReplaceDialog(m_pFindReplaceDialog);
+                               m_pFindReplaceDialog = NULL;
+                       }
+               }
+
+               return 0;
+       }
+
+       LRESULT OnEditFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->FindReplace(TRUE);
+
+               return 0;
+       }
+
+       LRESULT OnEditRepeat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+
+               // If the user is holding down SHIFT when hitting F3, we'll
+               // search in reverse. Otherwise, we'll search forward.
+               // (be sure to have an accelerator mapped to ID_EDIT_REPEAT
+               // for both F3 and Shift+F3)
+               m_bFindDown = !((::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000);
+
+               if(m_sFindNext.IsEmpty())
+               {
+                       pT->FindReplace(TRUE);
+               }
+               else
+               {
+                       if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
+                               pT->TextNotFound(m_sFindNext);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnEditReplace(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+
+               DWORD style = pT->GetStyle();
+               if((style & ES_READONLY) != ES_READONLY)
+               {
+                       pT->FindReplace(FALSE);
+               }
+               else
+               {
+                       // Don't allow replace when the edit control is read only
+                       bHandled = FALSE;
+               }
+
+               return 0;
+       }
+
+// Operations (overrideable)
+       TFindReplaceDialog* CreateFindReplaceDialog(BOOL bFindOnly, // TRUE for Find, FALSE for FindReplace
+                       LPCTSTR lpszFindWhat,
+                       LPCTSTR lpszReplaceWith = NULL,
+                       DWORD dwFlags = FR_DOWN,
+                       HWND hWndParent = NULL)
+       {
+               // You can override all of this in a derived class
+
+               TFindReplaceDialog* findReplaceDialog = new TFindReplaceDialog();
+               if(findReplaceDialog == NULL)
+               {
+                       ::MessageBeep(MB_ICONHAND);
+               }
+               else
+               {
+                       HWND hWndFindReplace = findReplaceDialog->Create(bFindOnly,
+                               lpszFindWhat, lpszReplaceWith, dwFlags, hWndParent);
+                       if(hWndFindReplace == NULL)
+                       {
+                               delete findReplaceDialog;
+                               findReplaceDialog = NULL;
+                       }
+                       else
+                       {
+                               findReplaceDialog->SetActiveWindow();
+                               findReplaceDialog->ShowWindow(SW_SHOW);
+                       }
+               }
+
+               return findReplaceDialog;
+       }
+
+       void AdjustDialogPosition(HWND hWndDialog)
+       {
+               ATLASSERT((hWndDialog != NULL) && ::IsWindow(hWndDialog));
+
+               T* pT = static_cast<T*>(this);
+               LONG nStartChar = 0, nEndChar = 0;
+               // Send EM_GETSEL so we can use both Edit and RichEdit
+               // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&)
+               ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
+               POINT point = pT->PosFromChar(nStartChar);
+               ::ClientToScreen(pT->GetParent(), &point);
+               CRect rect;
+               ::GetWindowRect(hWndDialog, &rect);
+               if(rect.PtInRect(point))
+               {
+                       if(point.y > rect.Height())
+                       {
+                               rect.OffsetRect(0, point.y - rect.bottom - 20);
+                       }
+                       else
+                       {
+                               int nVertExt = GetSystemMetrics(SM_CYSCREEN);
+                               if(point.y + rect.Height() < nVertExt)
+                                       rect.OffsetRect(0, 40 + point.y - rect.top);
+                       }
+
+                       ::MoveWindow(hWndDialog, rect.left, rect.top, rect.Width(), rect.Height(), TRUE);
+               }
+       }
+
+       DWORD GetFindReplaceDialogFlags(void) const
+       {
+               DWORD dwFlags = 0;
+
+               if(m_bFindDown)
+                       dwFlags |= FR_DOWN;
+               if(m_bMatchCase)
+                       dwFlags |= FR_MATCHCASE;
+               if(m_bWholeWord)
+                       dwFlags |= FR_WHOLEWORD;
+
+               return dwFlags;
+       }
+
+       void FindReplace(BOOL bFindOnly)
+       {
+               T* pT = static_cast<T*>(this);
+               m_bFirstSearch = TRUE;
+               if(m_pFindReplaceDialog != NULL)
+               {
+                       if(m_bFindOnly == bFindOnly)
+                       {
+                               m_pFindReplaceDialog->SetActiveWindow();
+                               m_pFindReplaceDialog->ShowWindow(SW_SHOW);
+                               return;
+                       }
+                       else
+                       {
+                               m_pFindReplaceDialog->SendMessage(WM_CLOSE);
+                               ATLASSERT(m_pFindReplaceDialog == NULL);
+                       }
+               }
+
+               ATLASSERT(m_pFindReplaceDialog == NULL);
+
+               _CSTRING_NS::CString findNext;
+               pT->GetSelText(findNext);
+               // if selection is empty or spans multiple lines use old find text
+               if(findNext.IsEmpty() || (findNext.FindOneOf(_T("\n\r")) != -1))
+                       findNext = m_sFindNext;
+               _CSTRING_NS::CString replaceWith = m_sReplaceWith;
+               DWORD dwFlags = pT->GetFindReplaceDialogFlags();
+
+               m_pFindReplaceDialog = pT->CreateFindReplaceDialog(bFindOnly,
+                       findNext, replaceWith, dwFlags, pT->operator HWND());
+               ATLASSERT(m_pFindReplaceDialog != NULL);
+               if(m_pFindReplaceDialog != NULL)
+                       m_bFindOnly = bFindOnly;
+       }
+
+       BOOL SameAsSelected(LPCTSTR lpszCompare, BOOL bMatchCase, BOOL /*bWholeWord*/)
+       {
+               T* pT = static_cast<T*>(this);
+
+               // check length first
+               size_t nLen = lstrlen(lpszCompare);
+               LONG nStartChar = 0, nEndChar = 0;
+               // Send EM_GETSEL so we can use both Edit and RichEdit
+               // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&)
+               ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
+               if(nLen != (size_t)(nEndChar - nStartChar))
+                       return FALSE;
+
+               // length is the same, check contents
+               _CSTRING_NS::CString selectedText;
+               pT->GetSelText(selectedText);
+
+               return (bMatchCase && selectedText.Compare(lpszCompare) == 0) ||
+                       (!bMatchCase && selectedText.CompareNoCase(lpszCompare) == 0);
+       }
+
+       void TextNotFound(LPCTSTR lpszFind)
+       {
+               T* pT = static_cast<T*>(this);
+               m_bFirstSearch = TRUE;
+               pT->OnTextNotFound(lpszFind);
+       }
+
+       _CSTRING_NS::CString GetTranslationText(enum TranslationTextItem eItem) const
+       {
+               _CSTRING_NS::CString text;
+               switch(eItem)
+               {
+               case eText_OnReplaceAllMessage:
+                       text = _T("Replaced %d occurances of \"%s\" with \"%s\"");
+                       break;
+               case eText_OnReplaceAllTitle:
+                       text = _T("Replace All");
+                       break;
+               case eText_OnTextNotFoundMessage:
+                       text = _T("Unable to find the text \"%s\"");
+                       break;
+               case eText_OnTextNotFoundTitle:
+                       text = _T("Text not found");
+                       break;
+               }
+
+               return text;
+       }
+
+// Overrideable Handlers
+       void OnFindNext(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord)
+       {
+               T* pT = static_cast<T*>(this);
+
+               m_sFindNext = lpszFind;
+               m_bMatchCase = bMatchCase;
+               m_bWholeWord = bWholeWord;
+               m_bFindDown = bFindDown;
+
+               if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
+                       pT->TextNotFound(m_sFindNext);
+               else
+                       pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND());
+       }
+
+       void OnReplaceSel(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord, LPCTSTR lpszReplace)
+       {
+               T* pT = static_cast<T*>(this);
+
+               m_sFindNext = lpszFind;
+               m_sReplaceWith = lpszReplace;
+               m_bMatchCase = bMatchCase;
+               m_bWholeWord = bWholeWord;
+               m_bFindDown = bFindDown;
+
+               if(pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord))
+                       pT->ReplaceSel(m_sReplaceWith);
+
+               if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
+                       pT->TextNotFound(m_sFindNext);
+               else
+                       pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND());
+       }
+
+       void OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bMatchCase, BOOL bWholeWord)
+       {
+               T* pT = static_cast<T*>(this);
+
+               m_sFindNext = lpszFind;
+               m_sReplaceWith = lpszReplace;
+               m_bMatchCase = bMatchCase;
+               m_bWholeWord = bWholeWord;
+               m_bFindDown = TRUE;
+
+               // no selection or different than what looking for
+               if(!pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord))
+               {
+                       if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
+                       {
+                               pT->TextNotFound(m_sFindNext);
+                               return;
+                       }
+               }
+
+               pT->OnReplaceAllCoreBegin();
+
+               int replaceCount=0;
+               do
+               {
+                       ++replaceCount;
+                       pT->ReplaceSel(m_sReplaceWith);
+               } while(pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown));
+
+               pT->OnReplaceAllCoreEnd(replaceCount);
+       }
+
+       void OnReplaceAllCoreBegin()
+       {
+               T* pT = static_cast<T*>(this);
+
+               m_hOldCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
+
+               pT->HideSelection(TRUE, FALSE);
+
+       }
+
+       void OnReplaceAllCoreEnd(int replaceCount)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->HideSelection(FALSE, FALSE);
+
+               ::SetCursor(m_hOldCursor);
+
+               _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnReplaceAllMessage);
+               if(message.GetLength() > 0)
+               {
+                       _CSTRING_NS::CString formattedMessage;
+                       formattedMessage.Format(message,
+                               replaceCount, m_sFindNext, m_sReplaceWith);
+                       if(m_pFindReplaceDialog != NULL)
+                       {
+                               m_pFindReplaceDialog->MessageBox(formattedMessage,
+                                       pT->GetTranslationText(eText_OnReplaceAllTitle),
+                                       MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
+                       }
+                       else
+                       {
+                               pT->MessageBox(formattedMessage,
+                                       pT->GetTranslationText(eText_OnReplaceAllTitle),
+                                       MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
+                       }
+               }
+       }
+
+       void OnTextNotFound(LPCTSTR lpszFind)
+       {
+               T* pT = static_cast<T*>(this);
+               _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnTextNotFoundMessage);
+               if(message.GetLength() > 0)
+               {
+                       _CSTRING_NS::CString formattedMessage;
+                       formattedMessage.Format(message, lpszFind);
+                       if(m_pFindReplaceDialog != NULL)
+                       {
+                               m_pFindReplaceDialog->MessageBox(formattedMessage,
+                                       pT->GetTranslationText(eText_OnTextNotFoundTitle),
+                                       MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
+                       }
+                       else
+                       {
+                               pT->MessageBox(formattedMessage,
+                                       pT->GetTranslationText(eText_OnTextNotFoundTitle),
+                                       MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
+                       }
+               }
+               else
+               {
+                       ::MessageBeep(MB_ICONHAND);
+               }
+       }
+
+       void OnTerminatingFindReplaceDialog(TFindReplaceDialog*& /*findReplaceDialog*/)
+       {
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CEditFindReplaceImpl - Mixin class for implementing Find/Replace for CEdit
+// based window classes.
+
+// Chain to CEditFindReplaceImpl message map. Your class must also derive from CEdit.
+// Example:
+// class CMyEdit : public CWindowImpl<CMyEdit, CEdit>,
+//                 public CEditFindReplaceImpl<CMyEdit>
+// {
+// public:
+//      BEGIN_MSG_MAP(CMyEdit)
+//              // your handlers...
+//              CHAIN_MSG_MAP_ALT(CEditFindReplaceImpl<CMyEdit>, 1)
+//      END_MSG_MAP()
+//      // other stuff...
+// };
+
+template <class T, class TFindReplaceDialog = CFindReplaceDialog>
+class CEditFindReplaceImpl : public CEditFindReplaceImplBase<T, TFindReplaceDialog>
+{
+protected:
+       typedef CEditFindReplaceImpl<T, TFindReplaceDialog> thisClass;
+       typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> baseClass;
+
+// Data members
+       LPTSTR m_pShadowBuffer;     // Special shadow buffer only used in some cases.
+       UINT m_nShadowSize;
+       int m_bShadowBufferNeeded;  // TRUE, FALSE, < 0 => Need to check
+
+public:
+// Constructors
+       CEditFindReplaceImpl() :
+               m_pShadowBuffer(NULL),
+               m_nShadowSize(0),
+               m_bShadowBufferNeeded(-1)
+       {
+       }
+
+       virtual ~CEditFindReplaceImpl()
+       {
+               if(m_pShadowBuffer != NULL)
+               {
+                       delete [] m_pShadowBuffer;
+                       m_pShadowBuffer = NULL;
+               }
+       }
+
+// Message Handlers
+       BEGIN_MSG_MAP(thisClass)
+       ALT_MSG_MAP(1)
+               CHAIN_MSG_MAP_ALT(baseClass, 1)
+       END_MSG_MAP()
+
+// Operations
+       // Supported only for RichEdit, so this does nothing for Edit
+       void HideSelection(BOOL /*bHide*/ = TRUE, BOOL /*bChangeStyle*/ = FALSE)
+       {
+       }
+
+// Operations (overrideable)
+       BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE)
+       {
+               T* pT = static_cast<T*>(this);
+
+               ATLASSERT(lpszFind != NULL);
+               ATLASSERT(*lpszFind != _T('\0'));
+
+               UINT nLen = pT->GetBufferLength();
+               int nStartChar = 0, nEndChar = 0;
+               pT->GetSel(nStartChar, nEndChar);
+               UINT nStart = nStartChar;
+               int iDir = bFindDown ? +1 : -1;
+
+               // can't find a match before the first character
+               if(nStart == 0 && iDir < 0)
+                       return FALSE;
+
+               LPCTSTR lpszText = pT->LockBuffer();
+
+               bool isDBCS = false;
+#ifdef _MBCS
+               CPINFO info = { 0 };
+               ::GetCPInfo(::GetOEMCP(), &info);
+               isDBCS = (info.MaxCharSize > 1);
+#endif
+
+               if(iDir < 0)
+               {
+                       // always go back one for search backwards
+                       nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart));
+               }
+               else if(nStartChar != nEndChar && pT->SameAsSelected(lpszFind, bMatchCase, bWholeWord))
+               {
+                       // easy to go backward/forward with SBCS
+#ifndef _UNICODE
+                       if(::IsDBCSLeadByte(lpszText[nStart]))
+                               nStart++;
+#endif
+                       nStart += iDir;
+               }
+
+               // handle search with nStart past end of buffer
+               UINT nLenFind = ::lstrlen(lpszFind);
+               if(nStart + nLenFind - 1 >= nLen)
+               {
+                       if(iDir < 0 && nLen >= nLenFind)
+                       {
+                               if(isDBCS)
+                               {
+                                       // walk back to previous character n times
+                                       nStart = nLen;
+                                       int n = nLenFind;
+                                       while(n--)
+                                       {
+                                               nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart));
+                                       }
+                               }
+                               else
+                               {
+                                       // single-byte character set is easy and fast
+                                       nStart = nLen - nLenFind;
+                               }
+                               ATLASSERT(nStart + nLenFind - 1 <= nLen);
+                       }
+                       else
+                       {
+                               pT->UnlockBuffer();
+                               return FALSE;
+                       }
+               }
+
+               // start the search at nStart
+               LPCTSTR lpsz = lpszText + nStart;
+               typedef int (WINAPI* CompareProc)(LPCTSTR str1, LPCTSTR str2);
+               CompareProc pfnCompare = bMatchCase ? lstrcmp : lstrcmpi;
+
+               if(isDBCS)
+               {
+                       // double-byte string search
+                       LPCTSTR lpszStop = NULL;
+                       if(iDir > 0)
+                       {
+                               // start at current and find _first_ occurrance
+                               lpszStop = lpszText + nLen - nLenFind + 1;
+                       }
+                       else
+                       {
+                               // start at top and find _last_ occurrance
+                               lpszStop = lpsz;
+                               lpsz = lpszText;
+                       }
+
+                       LPCTSTR lpszFound = NULL;
+                       while(lpsz <= lpszStop)
+                       {
+#ifndef _UNICODE
+                               if(!bMatchCase || (*lpsz == *lpszFind && (!::IsDBCSLeadByte(*lpsz) || lpsz[1] == lpszFind[1])))
+#else
+                               if(!bMatchCase || (*lpsz == *lpszFind && lpsz[1] == lpszFind[1]))
+#endif
+                               {
+                                       LPTSTR lpch = (LPTSTR)(lpsz + nLenFind);
+                                       TCHAR chSave = *lpch;
+                                       *lpch = _T('\0');
+                                       int nResult = (*pfnCompare)(lpsz, lpszFind);
+                                       *lpch = chSave;
+                                       if(nResult == 0)
+                                       {
+                                               lpszFound = lpsz;
+                                               if(iDir > 0)
+                                                       break;
+                                       }
+                               }
+                               lpsz = ::CharNext(lpsz);
+                       }
+                       pT->UnlockBuffer();
+
+                       if(lpszFound != NULL)
+                       {
+                               int n = (int)(lpszFound - lpszText);
+                               pT->SetSel(n, n + nLenFind);
+                               return TRUE;
+                       }
+               }
+               else
+               {
+                       // single-byte string search
+                       UINT nCompare;
+                       if(iDir < 0)
+                               nCompare = (UINT)(lpsz - lpszText) + 1;
+                       else
+                               nCompare = nLen - (UINT)(lpsz - lpszText) - nLenFind + 1;
+
+                       while(nCompare > 0)
+                       {
+                               ATLASSERT(lpsz >= lpszText);
+                               ATLASSERT(lpsz + nLenFind - 1 <= lpszText + nLen - 1);
+
+                               LPSTR lpch = (LPSTR)(lpsz + nLenFind);
+                               char chSave = *lpch;
+                               *lpch = '\0';
+                               int nResult = (*pfnCompare)(lpsz, lpszFind);
+                               *lpch = chSave;
+                               if(nResult == 0)
+                               {
+                                       pT->UnlockBuffer();
+                                       int n = (int)(lpsz - lpszText);
+                                       pT->SetSel(n, n + nLenFind);
+                                       return TRUE;
+                               }
+
+                               // restore character at end of search
+                               *lpch = chSave;
+
+                               // move on to next substring
+                               nCompare--;
+                               lpsz += iDir;
+                       }
+                       pT->UnlockBuffer();
+               }
+
+               return FALSE;
+       }
+
+       LPCTSTR LockBuffer() const
+       {
+               const T* pT = static_cast<const T*>(this);
+
+               ATLASSERT(pT->m_hWnd != NULL);
+
+               BOOL useShadowBuffer = pT->UseShadowBuffer();
+               if(useShadowBuffer)
+               {
+                       if(m_pShadowBuffer == NULL || pT->GetModify())
+                       {
+                               ATLASSERT(m_pShadowBuffer != NULL || m_nShadowSize == 0);
+                               UINT nSize = pT->GetWindowTextLength() + 1;
+                               if(nSize > m_nShadowSize)
+                               {
+                                       // need more room for shadow buffer
+                                       T* pThisNoConst = const_cast<T*>(pT);
+                                       delete[] m_pShadowBuffer;
+                                       pThisNoConst->m_pShadowBuffer = NULL;
+                                       pThisNoConst->m_nShadowSize = 0;
+                                       pThisNoConst->m_pShadowBuffer = new TCHAR[nSize];
+                                       pThisNoConst->m_nShadowSize = nSize;
+                               }
+
+                               // update the shadow buffer with GetWindowText
+                               ATLASSERT(m_nShadowSize >= nSize);
+                               ATLASSERT(m_pShadowBuffer != NULL);
+                               pT->GetWindowText(m_pShadowBuffer, nSize);
+                       }
+
+                       return m_pShadowBuffer;
+               }
+
+               HLOCAL hLocal = pT->GetHandle();
+               ATLASSERT(hLocal != NULL);
+               LPCTSTR lpszText = (LPCTSTR)::LocalLock(hLocal);
+               ATLASSERT(lpszText != NULL);
+
+               return lpszText;
+       }
+
+       void UnlockBuffer() const
+       {
+               const T* pT = static_cast<const T*>(this);
+
+               ATLASSERT(pT->m_hWnd != NULL);
+
+               BOOL useShadowBuffer = pT->UseShadowBuffer();
+               if(!useShadowBuffer)
+               {
+                       HLOCAL hLocal = pT->GetHandle();
+                       ATLASSERT(hLocal != NULL);
+                       ::LocalUnlock(hLocal);
+               }
+       }
+
+       UINT GetBufferLength() const
+       {
+               const T* pT = static_cast<const T*>(this);
+
+               ATLASSERT(pT->m_hWnd != NULL);
+               UINT nLen = 0;
+               LPCTSTR lpszText = pT->LockBuffer();
+               if(lpszText != NULL)
+                       nLen = ::lstrlen(lpszText);
+               pT->UnlockBuffer();
+
+               return nLen;
+       }
+
+       LONG EndOfLine(LPCTSTR lpszText, UINT nLen, UINT nIndex) const
+       {
+               LPCTSTR lpsz = lpszText + nIndex;
+               LPCTSTR lpszStop = lpszText + nLen;
+               while(lpsz < lpszStop && *lpsz != _T('\r'))
+                       ++lpsz;
+               return LONG(lpsz - lpszText);
+       }
+
+       LONG GetSelText(_CSTRING_NS::CString& strText) const
+       {
+               const T* pT = static_cast<const T*>(this);
+
+               int nStartChar = 0, nEndChar = 0;
+               pT->GetSel(nStartChar, nEndChar);
+               ATLASSERT((UINT)nEndChar <= pT->GetBufferLength());
+               LPCTSTR lpszText = pT->LockBuffer();
+               LONG nLen = pT->EndOfLine(lpszText, nEndChar, nStartChar) - nStartChar;
+               SecureHelper::memcpy_x(strText.GetBuffer(nLen), nLen * sizeof(TCHAR), lpszText + nStartChar, nLen * sizeof(TCHAR));
+               strText.ReleaseBuffer(nLen);
+               pT->UnlockBuffer();
+
+               return nLen;
+       }
+
+       BOOL UseShadowBuffer(void) const
+       {
+               const T* pT = static_cast<const T*>(this);
+
+               if(pT->m_bShadowBufferNeeded < 0)
+               {
+                       T* pThisNoConst = const_cast<T*>(pT);
+
+                       OSVERSIONINFO ovi = { 0 };
+                       ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+                       ::GetVersionEx(&ovi);
+
+                       bool bWin9x = (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+                       if(bWin9x)
+                       {
+                               // Windows 95, 98, ME
+                               // Under Win9x, it is necessary to maintain a shadow buffer.
+                               // It is only updated when the control contents have been changed.
+                               pThisNoConst->m_bShadowBufferNeeded = TRUE;
+                       }
+                       else
+                       {
+                               // Windows NT, 2000, XP, etc.
+                               pThisNoConst->m_bShadowBufferNeeded = FALSE;
+
+#ifndef _UNICODE
+                               // On Windows XP (or later), if common controls version 6 is in use
+                               // (such as via theming), then EM_GETHANDLE will always return a UNICODE string.
+                               // If theming is enabled and Common Controls version 6 is in use,
+                               // you're really not suppose to superclass or subclass common controls
+                               // with an ANSI windows procedure (so its best to only theme if you use UNICODE).
+                               // Using a shadow buffer uses GetWindowText instead, so it solves
+                               // this problem for us (although it makes it a little less efficient).
+
+                               if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5))
+                               {
+                                       // We use DLLVERSIONINFO_private so we don't have to depend on shlwapi.h
+                                       typedef struct _DLLVERSIONINFO_private
+                                       {
+                                               DWORD cbSize;
+                                               DWORD dwMajorVersion;
+                                               DWORD dwMinorVersion;
+                                               DWORD dwBuildNumber;
+                                               DWORD dwPlatformID;
+                                       } DLLVERSIONINFO_private;
+
+                                       HMODULE hModule = ::LoadLibrary("comctl32.dll");
+                                       if(hModule != NULL)
+                                       {
+                                               typedef HRESULT (CALLBACK *LPFN_DllGetVersion)(DLLVERSIONINFO_private *);
+                                               LPFN_DllGetVersion fnDllGetVersion = (LPFN_DllGetVersion)::GetProcAddress(hModule, "DllGetVersion");
+                                               if(fnDllGetVersion != NULL)
+                                               {
+                                                       DLLVERSIONINFO_private version = { 0 };
+                                                       version.cbSize = sizeof(DLLVERSIONINFO_private);
+                                                       if(SUCCEEDED(fnDllGetVersion(&version)))
+                                                       {
+                                                               if(version.dwMajorVersion >= 6)
+                                                               {
+                                                                       pThisNoConst->m_bShadowBufferNeeded = TRUE;
+
+                                                                       ATLTRACE2(atlTraceUI, 0, _T("Warning: You have compiled for MBCS/ANSI but are using common controls version 6 or later (likely through a manifest file).\r\n"));
+                                                                       ATLTRACE2(atlTraceUI, 0, _T("If you use common controls version 6 or later, you should only do so for UNICODE builds.\r\n"));
+                                                               }
+                                                       }
+                                               }
+
+                                               ::FreeLibrary(hModule);
+                                               hModule = NULL;
+                                       }
+                               }
+#endif // !_UNICODE
+                       }
+               }
+
+               return (pT->m_bShadowBufferNeeded == TRUE);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CRichEditFindReplaceImpl - Mixin class for implementing Find/Replace for CRichEditCtrl
+// based window classes.
+
+// Chain to CRichEditFindReplaceImpl message map. Your class must also derive from CRichEditCtrl.
+// Example:
+// class CMyRichEdit : public CWindowImpl<CMyRichEdit, CRichEditCtrl>,
+//                     public CRichEditFindReplaceImpl<CMyRichEdit>
+// {
+// public:
+//      BEGIN_MSG_MAP(CMyRichEdit)
+//              // your handlers...
+//              CHAIN_MSG_MAP_ALT(CRichEditFindReplaceImpl<CMyRichEdit>, 1)
+//      END_MSG_MAP()
+//      // other stuff...
+// };
+
+template <class T, class TFindReplaceDialog = CFindReplaceDialog>
+class CRichEditFindReplaceImpl : public CEditFindReplaceImplBase<T, TFindReplaceDialog>
+{
+protected:
+       typedef CRichEditFindReplaceImpl<T, TFindReplaceDialog> thisClass;
+       typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> baseClass;
+
+public:
+       BEGIN_MSG_MAP(thisClass)
+       ALT_MSG_MAP(1)
+               CHAIN_MSG_MAP_ALT(baseClass, 1)
+       END_MSG_MAP()
+
+// Operations (overrideable)
+       BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE)
+       {
+               T* pT = static_cast<T*>(this);
+
+               ATLASSERT(lpszFind != NULL);
+               FINDTEXTEX ft = { 0 };
+
+               pT->GetSel(ft.chrg);
+               if(m_bFirstSearch)
+               {
+                       if(bFindDown)
+                               m_nInitialSearchPos = ft.chrg.cpMin;
+                       else
+                               m_nInitialSearchPos = ft.chrg.cpMax;
+                       m_bFirstSearch = FALSE;
+               }
+
+#if (_RICHEDIT_VER >= 0x0200)
+               ft.lpstrText = (LPTSTR)lpszFind;
+#else // !(_RICHEDIT_VER >= 0x0200)
+               USES_CONVERSION;
+               ft.lpstrText = T2A((LPTSTR)lpszFind);
+#endif // !(_RICHEDIT_VER >= 0x0200)
+
+               if(ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection
+               {
+                       if(bFindDown)
+                       {
+                               ft.chrg.cpMin++;
+                       }
+                       else
+                       {
+                               // won't wraparound backwards
+                               ft.chrg.cpMin = max(ft.chrg.cpMin, 0);
+                       }
+               }
+
+               DWORD dwFlags = bMatchCase ? FR_MATCHCASE : 0;
+               dwFlags |= bWholeWord ? FR_WHOLEWORD : 0;
+
+               ft.chrg.cpMax = pT->GetTextLength() + m_nInitialSearchPos;
+
+               if(bFindDown)
+               {
+                       if(m_nInitialSearchPos >= 0)
+                               ft.chrg.cpMax = pT->GetTextLength();
+
+                       dwFlags |= FR_DOWN;
+                       ATLASSERT(ft.chrg.cpMax >= ft.chrg.cpMin);
+               }
+               else
+               {
+                       if(m_nInitialSearchPos >= 0)
+                               ft.chrg.cpMax = 0;
+
+                       dwFlags &= ~FR_DOWN;
+                       ATLASSERT(ft.chrg.cpMax <= ft.chrg.cpMin);
+               }
+
+               BOOL bRet = FALSE;
+
+               if(pT->FindAndSelect(dwFlags, ft) != -1)
+               {
+                       bRet = TRUE;   // we found the text
+               }
+               else if(m_nInitialSearchPos > 0)
+               {
+                       // if the original starting point was not the beginning
+                       // of the buffer and we haven't already been here
+                       if(bFindDown)
+                       {
+                               ft.chrg.cpMin = 0;
+                               ft.chrg.cpMax = m_nInitialSearchPos;
+                       }
+                       else
+                       {
+                               ft.chrg.cpMin = pT->GetTextLength();
+                               ft.chrg.cpMax = m_nInitialSearchPos;
+                       }
+                       m_nInitialSearchPos = m_nInitialSearchPos - pT->GetTextLength();
+
+                       bRet = (pT->FindAndSelect(dwFlags, ft) != -1) ? TRUE : FALSE;
+               }
+
+               return bRet;
+       }
+
+       long FindAndSelect(DWORD dwFlags, FINDTEXTEX& ft)
+       {
+               T* pT = static_cast<T*>(this);
+               LONG index = pT->FindText(dwFlags, ft);
+               if(index != -1) // i.e. we found something
+                       pT->SetSel(ft.chrgText);
+
+               return index;
+       }
+};
+
+}; // namespace WTL
+
+#endif // __ATLFIND_H__
diff --git a/include/WTL/Include/atlframe.h b/include/WTL/Include/atlframe.h
new file mode 100644 (file)
index 0000000..00358c3
--- /dev/null
@@ -0,0 +1,3465 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLFRAME_H__
+#define __ATLFRAME_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlframe.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atlframe.h requires atlwin.h to be included first
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CFrameWindowImpl<T, TBase, TWinTraits>
+// CMDIWindow
+// CMDIFrameWindowImpl<T, TBase, TWinTraits>
+// CMDIChildWindowImpl<T, TBase, TWinTraits>
+// COwnerDraw<T>
+// CUpdateUIBase
+// CUpdateUI<T>
+// CDynamicUpdateUI<T>
+// CDialogResize<T>
+// CDoubleBufferImpl<T>
+// CDoubleBufferWindowImpl<T, TBase, TWinTraits>
+//
+// Global functions:
+//   AtlCreateSimpleToolBar()
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CFrameWndClassInfo - Manages frame window Windows class information
+
+class CFrameWndClassInfo
+{
+public:
+#ifndef _WIN32_WCE
+       enum { cchAutoName = 5 + sizeof(void*) * 2 };   // sizeof(void*) * 2 is the number of digits %p outputs
+       WNDCLASSEX m_wc;
+#else // CE specific
+       enum { cchAutoName = MAX_PATH };   // MAX_PATH because this can be set in the wizard generated CMainFrame::ActivatePreviousInstance to a user defined string.
+       WNDCLASS m_wc;
+#endif // !_WIN32_WCE
+       LPCTSTR m_lpszOrigName;
+       WNDPROC pWndProc;
+       LPCTSTR m_lpszCursorID;
+       BOOL m_bSystemCursor;
+       ATOM m_atom;
+       TCHAR m_szAutoName[cchAutoName];
+       UINT m_uCommonResourceID;
+
+#ifndef _WIN32_WCE
+       ATOM Register(WNDPROC* pProc)
+       {
+               if (m_atom == 0)
+               {
+                       CWindowCreateCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(m_atom == 0)
+                       {
+                               HINSTANCE hInst = ModuleHelper::GetModuleInstance();
+
+                               if (m_lpszOrigName != NULL)
+                               {
+                                       ATLASSERT(pProc != NULL);
+                                       LPCTSTR lpsz = m_wc.lpszClassName;
+                                       WNDPROC proc = m_wc.lpfnWndProc;
+
+                                       WNDCLASSEX wc = { 0 };
+                                       wc.cbSize = sizeof(WNDCLASSEX);
+                                       // try process local class first
+                                       if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
+                                       {
+                                               // try global class
+                                               if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
+                                               {
+                                                       lock.Unlock();
+                                                       return 0;
+                                               }
+                                       }
+                                       m_wc = wc;
+                                       pWndProc = m_wc.lpfnWndProc;
+                                       m_wc.lpszClassName = lpsz;
+                                       m_wc.lpfnWndProc = proc;
+                               }
+                               else
+                               {
+                                       m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
+                               }
+
+                               m_wc.hInstance = hInst;
+                               m_wc.style &= ~CS_GLOBALCLASS;   // we don't register global classes
+                               if (m_wc.lpszClassName == NULL)
+                               {
+#if (_WIN32_WINNT >= 0x0500) || defined(_WIN64)
+                                       SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%p"), &m_wc);
+#else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
+                                       SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
+#endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
+                                       m_wc.lpszClassName = m_szAutoName;
+                               }
+
+                               WNDCLASSEX wcTemp = m_wc;
+                               m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
+                               if (m_atom == 0)
+                               {
+                                       if(m_uCommonResourceID != 0)   // use it if not zero
+                                       {
+                                               m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
+                                               m_wc.hIconSm = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
+                                       }
+                                       m_atom = ::RegisterClassEx(&m_wc);
+                               }
+                       }
+
+                       lock.Unlock();
+               }
+
+               if (m_lpszOrigName != NULL)
+               {
+                       ATLASSERT(pProc != NULL);
+                       ATLASSERT(pWndProc != NULL);
+                       *pProc = pWndProc;
+               }
+
+               return m_atom;
+       }
+#else // CE specific
+       ATOM Register(WNDPROC* pProc)
+       {
+               if (m_atom == 0)
+               {
+                       CWindowCreateCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+
+                       if(m_atom == 0)
+                       {
+                               HINSTANCE hInst = ModuleHelper::GetModuleInstance();
+
+                               if (m_lpszOrigName != NULL)
+                               {
+                                       ATLASSERT(pProc != NULL);
+                                       LPCTSTR lpsz = m_wc.lpszClassName;
+                                       WNDPROC proc = m_wc.lpfnWndProc;
+
+                                       WNDCLASS wc = { 0 };
+                                       // try process local class first
+                                       if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
+                                       {
+                                               // try global class
+                                               if(!::GetClassInfo(NULL, m_lpszOrigName, &wc))
+                                               {
+                                                       lock.Unlock();
+                                                       return 0;
+                                               }
+                                       }
+                                       m_wc = wc;
+                                       pWndProc = m_wc.lpfnWndProc;
+                                       m_wc.lpszClassName = lpsz;
+                                       m_wc.lpfnWndProc = proc;
+                               }
+                               else
+                               {
+#if defined(GWES_CURSOR) || defined(GWES_MCURSOR)
+                                       m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
+#else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
+                                       m_wc.hCursor = NULL;
+#endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
+                               }
+
+                               m_wc.hInstance = hInst;
+                               m_wc.style &= ~CS_GLOBALCLASS;   // we don't register global classes
+                               if (m_wc.lpszClassName == NULL)
+                               {
+                                       wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
+                                       m_wc.lpszClassName = m_szAutoName;
+                               }
+
+                               WNDCLASS wcTemp = m_wc;
+                               m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
+                               if (m_atom == 0)
+                               {
+                                       if(m_uCommonResourceID != 0)   // use it if not zero
+                                               m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
+                                       m_atom = ::RegisterClass(&m_wc);
+                               }
+                       }
+
+                       lock.Unlock();
+               }
+
+               if (m_lpszOrigName != NULL)
+               {
+                       ATLASSERT(pProc != NULL);
+                       ATLASSERT(pWndProc != NULL);
+                       *pProc = pWndProc;
+               }
+
+               return m_atom;
+       }
+#endif // _WIN32_WCE
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros for declaring frame window WNDCLASS
+
+#ifndef _WIN32_WCE
+
+#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
+static WTL::CFrameWndClassInfo& GetWndClassInfo() \
+{ \
+       static WTL::CFrameWndClassInfo wc = \
+       { \
+               { sizeof(WNDCLASSEX), 0, StartWindowProc, \
+                 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
+               NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
+       }; \
+       return wc; \
+}
+
+#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
+static WTL::CFrameWndClassInfo& GetWndClassInfo() \
+{ \
+       static WTL::CFrameWndClassInfo wc = \
+       { \
+               { sizeof(WNDCLASSEX), style, StartWindowProc, \
+                 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
+               NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
+       }; \
+       return wc; \
+}
+
+#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
+static WTL::CFrameWndClassInfo& GetWndClassInfo() \
+{ \
+       static WTL::CFrameWndClassInfo wc = \
+       { \
+               { sizeof(WNDCLASSEX), 0, StartWindowProc, \
+                 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
+               OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
+       }; \
+       return wc; \
+}
+
+#else // CE specific
+
+#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
+static WTL::CFrameWndClassInfo& GetWndClassInfo() \
+{ \
+       static WTL::CFrameWndClassInfo wc = \
+       { \
+               { 0, StartWindowProc, \
+                 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
+               NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
+       }; \
+       return wc; \
+}
+
+#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
+static WTL::CFrameWndClassInfo& GetWndClassInfo() \
+{ \
+       static WTL::CFrameWndClassInfo wc = \
+       { \
+               { style, StartWindowProc, \
+                 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
+               NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
+       }; \
+       return wc; \
+}
+
+#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
+static WTL::CFrameWndClassInfo& GetWndClassInfo() \
+{ \
+       static WTL::CFrameWndClassInfo wc = \
+       { \
+               { NULL, StartWindowProc, \
+                 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \
+               OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
+       }; \
+       return wc; \
+}
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CFrameWindowImpl
+
+// Client window command chaining macro (only for frame windows)
+#define CHAIN_CLIENT_COMMANDS() \
+       if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
+               ::SendMessage(m_hWndClient, uMsg, wParam, lParam);
+
+// standard toolbar styles
+#define ATL_SIMPLE_TOOLBAR_STYLE \
+       (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS)
+// toolbar in a rebar pane
+#define ATL_SIMPLE_TOOLBAR_PANE_STYLE \
+       (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT)
+// standard rebar styles
+#if (_WIN32_IE >= 0x0400)
+  #define ATL_SIMPLE_REBAR_STYLE \
+       (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE)
+#else
+  #define ATL_SIMPLE_REBAR_STYLE \
+       (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS)
+#endif // !(_WIN32_IE >= 0x0400)
+// rebar without borders
+#if (_WIN32_IE >= 0x0400)
+  #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
+       (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER)
+#else
+  #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
+       (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER)
+#endif // !(_WIN32_IE >= 0x0400)
+
+// command bar support
+#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
+
+#define CBRM_GETCMDBAR                 (WM_USER + 301) // returns command bar HWND
+#define CBRM_GETMENU                   (WM_USER + 302) // returns loaded or attached menu
+#define CBRM_TRACKPOPUPMENU            (WM_USER + 303) // displays a popup menu
+
+struct _AtlFrameWnd_CmdBarPopupMenu
+{
+       int cbSize;
+       HMENU hMenu;
+       UINT uFlags;
+       int x;
+       int y;
+       LPTPMPARAMS lptpm;
+};
+
+#define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu
+
+#endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
+
+
+template <class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
+class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase, TWinTraits >
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, 0)
+
+// Data members
+       HWND m_hWndToolBar;
+       HWND m_hWndStatusBar;
+       HWND m_hWndClient;
+
+       HACCEL m_hAccel;
+
+#ifdef _WIN32_WCE
+       HWND m_hWndCECommandBar;
+#endif // _WIN32_WCE
+
+       struct _AtlToolBarData
+       {
+               WORD wVersion;
+               WORD wWidth;
+               WORD wHeight;
+               WORD wItemCount;
+               //WORD aItems[wItemCount]
+
+               WORD* items()
+                       { return (WORD*)(this+1); }
+       };
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       struct _ChevronMenuInfo
+       {
+               HMENU hMenu;
+               LPNMREBARCHEVRON lpnm;
+               bool bCmdBar;
+       };
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+
+// Constructor
+       CFrameWindowImplBase() : 
+#ifdef _WIN32_WCE
+               m_hWndCECommandBar(NULL),
+#endif // _WIN32_WCE
+               m_hWndToolBar(NULL), 
+               m_hWndStatusBar(NULL), 
+               m_hWndClient(NULL), 
+               m_hAccel(NULL)
+       { }
+
+// Methods
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
+       {
+               ATLASSERT(m_hWnd == NULL);
+
+               if(atom == 0)
+                       return NULL;
+
+               ModuleHelper::AddCreateWndData(&m_thunk.cd, this);
+
+               if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD))
+                       MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
+               if(rect.m_lpRect == NULL)
+                       rect.m_lpRect = &TBase::rcDefault;
+
+               HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName,
+                       dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left,
+                       rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu,
+                       ModuleHelper::GetModuleInstance(), lpCreateParam);
+
+               ATLASSERT(hWnd == NULL || m_hWnd == hWnd);
+
+               return hWnd;
+       }
+
+       static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE, 
+                       DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               HINSTANCE hInst = ModuleHelper::GetResourceInstance();
+               HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR);
+               if (hRsrc == NULL)
+                       return NULL;
+
+               HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc);
+               if (hGlobal == NULL)
+                       return NULL;
+
+               _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal);
+               if (pData == NULL)
+                       return NULL;
+               ATLASSERT(pData->wVersion == 1);
+
+               WORD* pItems = pData->items();
+               int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0);
+               CTempBuffer<TBBUTTON, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               TBBUTTON* pTBBtn = buff.Allocate(nItems);
+               ATLASSERT(pTBBtn != NULL);
+               if(pTBBtn == NULL)
+                       return NULL;
+
+               const int cxSeparator = 8;
+
+               // set initial separator (half width)
+               if(bInitialSeparator)
+               {
+                       pTBBtn[0].iBitmap = cxSeparator / 2;
+                       pTBBtn[0].idCommand = 0;
+                       pTBBtn[0].fsState = 0;
+                       pTBBtn[0].fsStyle = TBSTYLE_SEP;
+                       pTBBtn[0].dwData = 0;
+                       pTBBtn[0].iString = 0;
+               }
+
+               int nBmp = 0;
+               for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++)
+               {
+                       if(pItems[i] != 0)
+                       {
+                               pTBBtn[j].iBitmap = nBmp++;
+                               pTBBtn[j].idCommand = pItems[i];
+                               pTBBtn[j].fsState = TBSTATE_ENABLED;
+                               pTBBtn[j].fsStyle = TBSTYLE_BUTTON;
+                               pTBBtn[j].dwData = 0;
+                               pTBBtn[j].iString = 0;
+                       }
+                       else
+                       {
+                               pTBBtn[j].iBitmap = cxSeparator;
+                               pTBBtn[j].idCommand = 0;
+                               pTBBtn[j].fsState = 0;
+                               pTBBtn[j].fsStyle = TBSTYLE_SEP;
+                               pTBBtn[j].dwData = 0;
+                               pTBBtn[j].iString = 0;
+                       }
+               }
+
+#ifndef _WIN32_WCE
+               HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
+               if(hWnd == NULL)
+               {
+                       ATLASSERT(FALSE);
+                       return NULL;
+               }
+#else // CE specific
+               dwStyle;
+               nID;
+               // The toolbar must go onto the existing CommandBar or MenuBar
+               HWND hWnd = hWndParent;
+#endif // _WIN32_WCE
+
+               ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
+
+               // check if font is taller than our bitmaps
+               CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
+               if(font.IsNull())
+                       font = AtlGetDefaultGuiFont();
+               LOGFONT lf = { 0 };
+               font.GetLogFont(lf);
+               WORD cyFontHeight = (WORD)abs(lf.lfHeight);
+
+#ifndef _WIN32_WCE
+               WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID);
+               if(bitsPerPixel > 4)
+               {
+                       COLORREF crMask = CLR_DEFAULT;
+                       if(bitsPerPixel == 32)
+                       {
+                               // 32-bit color bitmap with alpha channel (valid for Windows XP and later)
+                               crMask = CLR_NONE;
+                       }
+                       HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
+                       ATLASSERT(hImageList != NULL);
+                       ::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
+               }
+               else
+#endif // !_WIN32_WCE
+               {
+                       TBADDBITMAP tbab = { 0 };
+                       tbab.hInst = hInst;
+                       tbab.nID = nResourceID;
+                       ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab);
+               }
+
+               ::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn);
+               ::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, max(pData->wHeight, cyFontHeight)));
+               const int cxyButtonMargin = 7;
+               ::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + cxyButtonMargin, max(pData->wHeight, cyFontHeight) + cxyButtonMargin));
+
+               return hWnd;
+       }
+
+#ifndef _WIN32_WCE
+       static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               // Ensure style combinations for proper rebar painting
+               if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER)
+                       dwStyle &= ~WS_BORDER;
+               else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER))
+                       dwStyle |= CCS_NODIVIDER;
+
+               // Create rebar window
+               HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
+               if(hWndReBar == NULL)
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n"));
+                       return NULL;
+               }
+
+               // Initialize and send the REBARINFO structure
+               REBARINFO rbi = { 0 };
+               rbi.cbSize = sizeof(REBARINFO);
+               rbi.fMask  = 0;
+               if(!::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi))
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.\n"));
+                       ::DestroyWindow(hWndReBar);
+                       return NULL;
+               }
+
+               return hWndReBar;
+       }
+
+       BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               ATLASSERT(!::IsWindow(m_hWndToolBar));
+               m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID);
+               return (m_hWndToolBar != NULL);
+       }
+
+       static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nID = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
+       {
+               ATLASSERT(::IsWindow(hWndReBar));   // must be already created
+#ifdef _DEBUG
+               // block - check if this is really a rebar
+               {
+                       TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 };
+                       ::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME));
+                       ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0);
+               }
+#endif // _DEBUG
+               ATLASSERT(::IsWindow(hWndBand));   // must be already created
+
+               // Get number of buttons on the toolbar
+               int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L);
+
+               // Set band info structure
+               REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
+#if (_WIN32_IE >= 0x0400)
+               rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE;
+#else
+               rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE;
+#endif // !(_WIN32_IE >= 0x0400)
+               if(lpstrTitle != NULL)
+                       rbBand.fMask |= RBBIM_TEXT;
+               rbBand.fStyle = RBBS_CHILDEDGE;
+#if (_WIN32_IE >= 0x0500)
+               if(nBtnCount > 0)   // add chevron style for toolbar with buttons
+                       rbBand.fStyle |= RBBS_USECHEVRON;
+#endif // (_WIN32_IE >= 0x0500)
+               if(bNewRow)
+                       rbBand.fStyle |= RBBS_BREAK;
+
+               rbBand.lpText = (LPTSTR)lpstrTitle;
+               rbBand.hwndChild = hWndBand;
+               if(nID == 0)   // calc band ID
+                       nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L);
+               rbBand.wID = nID;
+
+               // Calculate the size of the band
+               BOOL bRet = FALSE;
+               RECT rcTmp = { 0 };
+               if(nBtnCount > 0)
+               {
+                       bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp);
+                       ATLASSERT(bRet);
+                       rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right;
+                       rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
+                       if(bFullWidthAlways)
+                       {
+                               rbBand.cxMinChild = rbBand.cx;
+                       }
+                       else if(lpstrTitle == NULL)
+                       {
+                               bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp);
+                               ATLASSERT(bRet);
+                               rbBand.cxMinChild = rcTmp.right;
+                       }
+                       else
+                       {
+                               rbBand.cxMinChild = 0;
+                       }
+               }
+               else    // no buttons, either not a toolbar or really has no buttons
+               {
+                       bRet = ::GetWindowRect(hWndBand, &rcTmp);
+                       ATLASSERT(bRet);
+                       rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left);
+                       rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0;
+                       rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
+               }
+
+#if (_WIN32_IE >= 0x0400)
+               rbBand.cxIdeal = rbBand.cx;
+#endif // (_WIN32_IE >= 0x0400)
+
+               // Add the band
+               LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
+               if(lRes == 0)
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n"));
+                       return FALSE;
+               }
+
+#if (_WIN32_IE >= 0x0501)
+               DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDSTYLE, 0, 0L);
+               ::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS);
+#endif // (_WIN32_IE >= 0x0501)
+
+               return TRUE;
+       }
+
+       BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWndToolBar));   // must be an existing rebar
+               ATLASSERT(::IsWindow(hWndBand));        // must be created
+               return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrTitle, bNewRow, cxWidth, bFullWidthAlways);
+       }
+
+#if (_WIN32_IE >= 0x0400)
+       void SizeSimpleReBarBands()
+       {
+               ATLASSERT(::IsWindow(m_hWndToolBar));   // must be an existing rebar
+
+               int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT, 0, 0L);
+
+               for(int i = 0; i < nCount; i++)
+               {
+                       REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
+                       rbBand.fMask = RBBIM_SIZE;
+                       BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBANDINFO, i, (LPARAM)&rbBand);
+                       ATLASSERT(bRet);
+                       RECT rect = { 0, 0, 0, 0 };
+                       ::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPARAM)&rect);
+                       rbBand.cx += rect.left + rect.right;
+                       bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO, i, (LPARAM)&rbBand);
+                       ATLASSERT(bRet);
+               }
+       }
+#endif // (_WIN32_IE >= 0x0400)
+#endif // _WIN32_WCE
+
+#ifndef _WIN32_WCE
+       BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
+#else // CE specific
+       BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
+#endif // _WIN32_WCE
+       {
+               ATLASSERT(!::IsWindow(m_hWndStatusBar));
+               m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID);
+               return (m_hWndStatusBar != NULL);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
+#else // CE specific
+       BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
+#endif // _WIN32_WCE
+       {
+               const int cchMax = 128;   // max text length is 127 for status bars (+1 for null)
+               TCHAR szText[cchMax];
+               szText[0] = 0;
+               ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
+               return CreateSimpleStatusBar(szText, dwStyle, nID);
+       }
+
+#ifdef _WIN32_WCE
+       BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, DWORD dwFlags = 0, int nCmdBarID = 1)
+       {
+               ATLASSERT(m_hWndCECommandBar == NULL);
+               ATLASSERT(m_hWndToolBar == NULL);
+
+               m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd, nCmdBarID);
+               if(m_hWndCECommandBar == NULL)
+                       return FALSE;
+
+               m_hWndToolBar = m_hWndCECommandBar;
+
+               BOOL bRet = TRUE;
+
+               if(pszMenu != NULL)
+                       bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar, IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu, iButton);
+
+               bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags, 0);
+
+               return bRet;
+       }
+
+#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
+       BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0)
+       {
+               ATLASSERT(m_hWndCECommandBar == NULL);
+
+               SHMENUBARINFO mbi = { 0 };
+               mbi.cbSize = sizeof(mbi);
+               mbi.hwndParent = m_hWnd;
+               mbi.dwFlags = dwFlags;
+               mbi.nToolBarId = nToolBarId;
+               mbi.hInstRes  = ModuleHelper::GetResourceInstance();
+               mbi.nBmpId = nBmpId;
+               mbi.cBmpImages = cBmpImages;
+               mbi.hwndMB = NULL;   // This gets set by SHCreateMenuBar
+
+               BOOL bRet = ::SHCreateMenuBar(&mbi);
+               if(bRet != FALSE)
+               {
+                       m_hWndCECommandBar = mbi.hwndMB;
+                       SizeToMenuBar();
+               }
+
+               return bRet;
+       }
+
+       void SizeToMenuBar()   // for menu bar only
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(::IsWindow(m_hWndCECommandBar));
+
+               RECT rect = { 0 };
+               GetWindowRect(&rect);
+               RECT rectMB = { 0 };
+               ::GetWindowRect(m_hWndCECommandBar, &rectMB);
+               int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - rect.top : rectMB.bottom - rect.top;
+               SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE);
+       }
+#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
+#endif // _WIN32_WCE
+
+       void UpdateLayout(BOOL bResizeBars = TRUE)
+       {
+               RECT rect = { 0 };
+               GetClientRect(&rect);
+
+               // position bars and offset their dimensions
+               UpdateBarsPosition(rect, bResizeBars);
+
+               // resize client window
+               if(m_hWndClient != NULL)
+                       ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
+                               rect.right - rect.left, rect.bottom - rect.top,
+                               SWP_NOZORDER | SWP_NOACTIVATE);
+       }
+
+       void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE)
+       {
+               // resize toolbar
+               if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE))
+               {
+                       if(bResizeBars)
+                       {
+                               ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0);
+                               ::InvalidateRect(m_hWndToolBar, NULL, FALSE);
+                       }
+                       RECT rectTB = { 0 };
+                       ::GetWindowRect(m_hWndToolBar, &rectTB);
+                       rect.top += rectTB.bottom - rectTB.top;
+               }
+
+               // resize status bar
+               if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
+               {
+                       if(bResizeBars)
+                               ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0);
+                       RECT rectSB = { 0 };
+                       ::GetWindowRect(m_hWndStatusBar, &rectSB);
+                       rect.bottom -= rectSB.bottom - rectSB.top;
+               }
+       }
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
+                       return TRUE;
+               return FALSE;
+       }
+
+       BEGIN_MSG_MAP(CFrameWindowImplBase)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
+#endif // !_WIN32_WCE
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+#ifndef _WIN32_WCE
+               NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA)
+               NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW)
+#endif // !_WIN32_WCE
+       END_MSG_MAP()
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_hWndClient != NULL)   // view will paint itself instead
+                       return 1;
+
+               bHandled = FALSE;
+               return 0;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               bHandled = FALSE;
+
+               if(m_hWndStatusBar == NULL)
+                       return 1;
+
+               WORD wFlags = HIWORD(wParam);
+               if(wFlags == 0xFFFF && lParam == NULL)   // menu closing
+               {
+                       ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L);
+               }
+               else
+               {
+                       const int cchBuff = 256;
+                       TCHAR szBuff[cchBuff];
+                       szBuff[0] = 0;
+                       if(!(wFlags & MF_POPUP))
+                       {
+                               WORD wID = LOWORD(wParam);
+                               // check for special cases
+                               if(wID >= 0xF000 && wID < 0xF1F0)   // system menu IDs
+                                       wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST);
+                               else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST)   // MRU items
+                                       wID = ATL_IDS_MRU_FILE;
+                               else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <= ATL_IDM_LAST_MDICHILD)   // MDI child windows
+                                       wID = ATL_IDS_MDICHILD;
+
+                               int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), wID, szBuff, cchBuff);
+                               for(int i = 0; i < nRet; i++)
+                               {
+                                       if(szBuff[i] == _T('\n'))
+                                       {
+                                               szBuff[i] = 0;
+                                               break;
+                                       }
+                               }
+                       }
+                       ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
+                       ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff);
+               }
+
+               return 1;
+       }
+#endif // !_WIN32_WCE
+
+       LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled)
+       {
+               if(m_hWndClient != NULL)
+                       ::SetFocus(m_hWndClient);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled)
+       {
+               if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0)
+                       ::PostQuitMessage(1);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh;
+               pDispInfo->szText[0] = 0;
+
+               if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
+               {
+                       const int cchBuff = 256;
+                       char szBuff[cchBuff];
+                       szBuff[0] = 0;
+                       int nRet = ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
+                       for(int i = 0; i < nRet; i++)
+                       {
+                               if(szBuff[i] == '\n')
+                               {
+                                       SecureHelper::strncpyA_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
+                                       break;
+                               }
+                       }
+#if (_WIN32_IE >= 0x0300)
+                       if(nRet > 0)   // string was loaded, save it
+                               pDispInfo->uFlags |= TTF_DI_SETITEM;
+#endif // (_WIN32_IE >= 0x0300)
+               }
+
+               return 0;
+       }
+
+       LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh;
+               pDispInfo->szText[0] = 0;
+
+               if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
+               {
+                       const int cchBuff = 256;
+                       wchar_t szBuff[cchBuff];
+                       szBuff[0] = 0;
+                       int nRet = ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
+                       for(int i = 0; i < nRet; i++)
+                       {
+                               if(szBuff[i] == L'\n')
+                               {
+                                       SecureHelper::strncpyW_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
+                                       break;
+                               }
+                       }
+#if (_WIN32_IE >= 0x0300)
+                       if(nRet > 0)   // string was loaded, save it
+                               pDispInfo->uFlags |= TTF_DI_SETITEM;
+#endif // (_WIN32_IE >= 0x0300)
+               }
+
+               return 0;
+       }
+#endif // !_WIN32_WCE
+
+// Implementation - chevron menu support
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       bool PrepareChevronMenu(_ChevronMenuInfo& cmi)
+       {
+               // get rebar and toolbar
+               REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
+               rbbi.fMask = RBBIM_CHILD;
+               BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBANDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi);
+               ATLASSERT(bRet);
+
+               // assume the band is a toolbar
+               ATL::CWindow wnd = rbbi.hwndChild;
+               int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT);
+               if(nCount <= 0)   // probably not a toolbar
+                       return false;
+
+               // check if it's a command bar
+               CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU);
+               cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL);
+
+               // build a menu from hidden items
+               CMenuHandle menu;
+               bRet = menu.CreatePopupMenu();
+               ATLASSERT(bRet);
+               RECT rcClient = { 0 };
+               bRet = wnd.GetClientRect(&rcClient);
+               ATLASSERT(bRet);
+               for(int i = 0; i < nCount; i++)
+               {
+                       TBBUTTON tbb = { 0 };
+                       bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&tbb);
+                       ATLASSERT(bRet);
+                       // skip hidden buttons
+                       if((tbb.fsState & TBSTATE_HIDDEN) != 0)
+                               continue;
+                       RECT rcButton = { 0 };
+                       bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)&rcButton);
+                       ATLASSERT(bRet);
+                       bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0);
+                       if(rcButton.right > rcClient.right)
+                       {
+                               if(tbb.fsStyle & BTNS_SEP)
+                               {
+                                       if(menu.GetMenuItemCount() > 0)
+                                               menu.AppendMenu(MF_SEPARATOR);
+                               }
+                               else if(cmi.bCmdBar)
+                               {
+                                       const int cchBuff = 200;
+                                       TCHAR szBuff[cchBuff] = { 0 };
+                                       CMenuItemInfo mii;
+                                       mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
+                                       mii.dwTypeData = szBuff;
+                                       mii.cch = cchBuff;
+                                       bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii);
+                                       ATLASSERT(bRet);
+                                       // Note: CmdBar currently supports only drop-down items
+                                       ATLASSERT(::IsMenu(mii.hSubMenu));
+                                       bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData);
+                                       ATLASSERT(bRet);
+                               }
+                               else
+                               {
+                                       // get button's text
+                                       const int cchBuff = 200;
+                                       TCHAR szBuff[cchBuff] = { 0 };
+                                       LPTSTR lpstrText = szBuff;
+                                       TBBUTTONINFO tbbi = { 0 };
+                                       tbbi.cbSize = sizeof(TBBUTTONINFO);
+                                       tbbi.dwMask = TBIF_TEXT;
+                                       tbbi.pszText = szBuff;
+                                       tbbi.cchText = cchBuff;
+                                       if(wnd.SendMessage(TB_GETBUTTONINFO, tbb.idCommand, (LPARAM)&tbbi) == -1 || lstrlen(szBuff) == 0)
+                                       {
+                                               // no text for this button, try a resource string
+                                               lpstrText = _T("");
+                                               int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff);
+                                               for(int n = 0; n < nRet; n++)
+                                               {
+                                                       if(szBuff[n] == _T('\n'))
+                                                       {
+                                                               lpstrText = &szBuff[n + 1];
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       bRet = menu.AppendMenu(MF_STRING | (bEnabled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText);
+                                       ATLASSERT(bRet);
+                               }
+                       }
+               }
+
+               if(menu.GetMenuItemCount() == 0)   // no hidden buttons after all
+               {
+                       menu.DestroyMenu();
+                       ::MessageBeep((UINT)-1);
+                       return false;
+               }
+
+               cmi.hMenu = menu;
+               return true;
+       }
+
+       void DisplayChevronMenu(_ChevronMenuInfo& cmi)
+       {
+#ifndef TPM_VERPOSANIMATION
+               const UINT TPM_VERPOSANIMATION = 0x1000L;   // Menu animation flag
+#endif
+               // convert chevron rect to screen coordinates
+               ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
+               POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom };
+               wndFrom.MapWindowPoints(NULL, &pt, 1);
+               RECT rc = cmi.lpnm->rc;
+               wndFrom.MapWindowPoints(NULL, &rc);
+               // set up flags and rect
+               UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0);
+               TPMPARAMS TPMParams = { 0 };
+               TPMParams.cbSize = sizeof(TPMPARAMS);
+               TPMParams.rcExclude = rc;
+               // check if this window has a command bar
+               HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L);
+               if(::IsWindow(hWndCmdBar))
+               {
+                       CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.hMenu, uMenuFlags, pt.x, pt.y, &TPMParams };
+                       ::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARAM)&CBRPopupMenu);
+               }
+               else
+               {
+                       CMenuHandle menu = cmi.hMenu;
+                       menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &TPMParams);
+               }
+       }
+
+       void CleanupChevronMenu(_ChevronMenuInfo& cmi)
+       {
+               CMenuHandle menu = cmi.hMenu;
+               // if menu is from a command bar, detach submenus so they are not destroyed
+               if(cmi.bCmdBar)
+               {
+                       for(int i = menu.GetMenuItemCount() - 1; i >=0; i--)
+                               menu.RemoveMenu(i, MF_BYPOSITION);
+               }
+               // destroy menu
+               menu.DestroyMenu();
+               // convert chevron rect to screen coordinates
+               ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
+               RECT rc = cmi.lpnm->rc;
+               wndFrom.MapWindowPoints(NULL, &rc);
+               // eat next message if click is on the same button
+               MSG msg = { 0 };
+               if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rc, msg.pt))
+                       ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+};
+
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
+class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits >
+{
+public:
+       HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
+       {
+               ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
+
+               dwStyle = T::GetWndStyle(dwStyle);
+               dwExStyle = T::GetWndExStyle(dwExStyle);
+
+               if(rect.m_lpRect == NULL)
+                       rect.m_lpRect = &TBase::rcDefault;
+
+               return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
+       }
+
+       HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
+       {
+               const int cchName = 256;
+               TCHAR szWindowName[cchName];
+               szWindowName[0] = 0;
+#ifndef _WIN32_WCE
+               ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
+               HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
+#else // CE specific
+               ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
+
+               // This always needs to be NULL for Windows CE.
+               // Frame Window menus have to go onto the CommandBar.
+               // Use CreateSimpleCECommandBar
+               HMENU hMenu = NULL;
+#endif // _WIN32_WCE
+
+               T* pT = static_cast<T*>(this);
+               HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
+
+               if(hWnd != NULL)
+                       m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
+
+               return hWnd;
+       }
+
+       BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               if(nResourceID == 0)
+                       nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
+#ifndef _WIN32_WCE
+               ATLASSERT(!::IsWindow(m_hWndToolBar));
+               m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
+               return (m_hWndToolBar != NULL);
+#else // CE specific
+               HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
+               return (hWnd != NULL);
+#endif // _WIN32_WCE
+       }
+
+#ifdef _WIN32_WCE
+       // CE specific variant that returns the handle of the toolbar
+       HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               if(nResourceID == 0)
+                       nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
+
+               return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
+       }
+#endif // _WIN32_WCE
+
+// message map and handlers
+       typedef CFrameWindowImplBase< TBase, TWinTraits >   _baseClass;
+
+       BEGIN_MSG_MAP(CFrameWindowImpl)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+#ifndef _ATL_NO_REBAR_SUPPORT
+#if (_WIN32_IE >= 0x0400)
+               NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
+#endif // (_WIN32_IE >= 0x0400)
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+               NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+#endif // !_ATL_NO_REBAR_SUPPORT
+               CHAIN_MSG_MAP(_baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(wParam != SIZE_MINIMIZED)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateLayout();
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+#ifndef _ATL_NO_REBAR_SUPPORT
+#if (_WIN32_IE >= 0x0400)
+       LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->UpdateLayout(FALSE);
+               return 0;
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+       LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
+               if(!pT->PrepareChevronMenu(cmi))
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+               // display a popup menu with hidden items
+               pT->DisplayChevronMenu(cmi);
+               // cleanup
+               pT->CleanupChevronMenu(cmi);
+               return 0;
+       }
+#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
+#endif // !_ATL_NO_REBAR_SUPPORT
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// AtlCreateSimpleToolBar - helper for creating simple toolbars
+
+#ifndef _WIN32_WCE
+
+inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE, 
+               DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+{
+       return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nResourceID, bInitialSeparator, dwStyle, nID);
+}
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMDIWindow
+
+#ifndef _WIN32_WCE
+
+#ifndef _WTL_MDIWINDOWMENU_TEXT
+#define _WTL_MDIWINDOWMENU_TEXT        _T("&Window")
+#endif
+
+class CMDIWindow : public ATL::CWindow
+{
+public:
+// Data members
+       HWND m_hWndMDIClient;
+       HMENU m_hMenu;
+
+// Constructors
+       CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL)
+       { }
+
+       CMDIWindow& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// Operations
+       HWND MDIGetActive(BOOL* lpbMaximized = NULL)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized);
+       }
+
+       void MDIActivate(HWND hWndChildToActivate)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               ATLASSERT(::IsWindow(hWndChildToActivate));
+               ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0);
+       }
+
+       void MDINext(HWND hWndChild, BOOL bPrevious = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild));
+               ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious);
+       }
+
+       void MDIMaximize(HWND hWndChildToMaximize)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               ATLASSERT(::IsWindow(hWndChildToMaximize));
+               ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0);
+       }
+
+       void MDIRestore(HWND hWndChildToRestore)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               ATLASSERT(::IsWindow(hWndChildToRestore));
+               ::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildToRestore, 0);
+       }
+
+       void MDIDestroy(HWND hWndChildToDestroy)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               ATLASSERT(::IsWindow(hWndChildToDestroy));
+               ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0);
+       }
+
+       BOOL MDICascade(UINT uFlags = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0);
+       }
+
+       BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0);
+       }
+
+       void MDIIconArrange()
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
+       }
+
+       HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow)
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow);
+       }
+
+       HMENU MDIRefreshMenu()
+       {
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+               return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
+       }
+
+// Additional operations
+       static HMENU GetStandardWindowMenu(HMENU hMenu)
+       {
+               int nCount = ::GetMenuItemCount(hMenu);
+               if(nCount == -1)
+                       return NULL;
+               int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION);
+               if(nLen == 0)
+                       return NULL;
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpszText = buff.Allocate(nLen + 1);
+               if(lpszText == NULL)
+                       return NULL;
+               if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen)
+                       return NULL;
+               if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0)
+                       return NULL;
+               return ::GetSubMenu(hMenu, nCount - 2);
+       }
+
+       void SetMDIFrameMenu()
+       {
+               HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu);
+               MDISetMenu(m_hMenu, hWindowMenu);
+               MDIRefreshMenu();
+               ::DrawMenuBar(GetMDIFrame());
+       }
+
+       HWND GetMDIFrame() const
+       {
+               return ::GetParent(m_hWndMDIClient);
+       }
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMDIFrameWindowImpl
+
+#ifndef _WIN32_WCE
+
+// MDI child command chaining macro (only for MDI frame windows)
+#define CHAIN_MDI_CHILD_COMMANDS() \
+       if(uMsg == WM_COMMAND) \
+       { \
+               HWND hWndChild = MDIGetActive(); \
+               if(hWndChild != NULL) \
+                       ::SendMessage(hWndChild, uMsg, wParam, lParam); \
+       }
+
+template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
+class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
+{
+public:
+       HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
+       {
+               m_hMenu = hMenu;
+               ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
+
+               dwStyle = T::GetWndStyle(dwStyle);
+               dwExStyle = T::GetWndExStyle(dwExStyle);
+
+               if(rect.m_lpRect == NULL)
+                       rect.m_lpRect = &TBase::rcDefault;
+
+               return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
+       }
+
+       HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
+       {
+               const int cchName = 256;
+               TCHAR szWindowName[cchName];
+               szWindowName[0] = 0;
+               ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
+               HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
+
+               T* pT = static_cast<T*>(this);
+               HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
+
+               if(hWnd != NULL)
+                       m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
+
+               return hWnd;
+       }
+
+       BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               ATLASSERT(!::IsWindow(m_hWndToolBar));
+               if(nResourceID == 0)
+                       nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
+               m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
+               return (m_hWndToolBar != NULL);
+       }
+
+       virtual WNDPROC GetWindowProc()
+       {
+               return MDIFrameWindowProc;
+       }
+
+       static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd;
+               // set a ptr to this message and save the old value
+#if (_ATL_VER >= 0x0700)
+               ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
+               const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
+#else // !(_ATL_VER >= 0x0700)
+               MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
+               const MSG* pOldMsg = pThis->m_pCurrentMsg;
+#endif // !(_ATL_VER >= 0x0700)
+               pThis->m_pCurrentMsg = &msg;
+               // pass to the message map to process
+               LRESULT lRes = 0;
+               BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
+               // restore saved value for the current message
+               ATLASSERT(pThis->m_pCurrentMsg == &msg);
+               pThis->m_pCurrentMsg = pOldMsg;
+               // do the default processing if message was not handled
+               if(!bRet)
+               {
+                       if(uMsg != WM_NCDESTROY)
+                               lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
+                       else
+                       {
+                               // unsubclass, if needed
+                               LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
+                               lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
+                               if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
+                                       ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
+#if (_ATL_VER >= 0x0700)
+                               // mark window as destryed
+                               pThis->m_dwState |= WINSTATE_DESTROYED;
+#else // !(_ATL_VER >= 0x0700)
+                               // clear out window handle
+                               HWND hWnd = pThis->m_hWnd;
+                               pThis->m_hWnd = NULL;
+                               // clean up after window is destroyed
+                               pThis->OnFinalMessage(hWnd);
+#endif // !(_ATL_VER >= 0x0700)
+                       }
+               }
+#if (_ATL_VER >= 0x0700)
+               if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg == NULL)
+               {
+                       // clear out window handle
+                       HWND hWnd = pThis->m_hWnd;
+                       pThis->m_hWnd = NULL;
+                       pThis->m_dwState &= ~WINSTATE_DESTROYED;
+                       // clean up after window is destroyed
+                       pThis->OnFinalMessage(hWnd);
+               }
+#endif // (_ATL_VER >= 0x0700)
+               return lRes;
+       }
+
+       // Overriden to call DefWindowProc which uses DefFrameProc
+       LRESULT DefWindowProc()
+       {
+               const MSG* pMsg = m_pCurrentMsg;
+               LRESULT lRes = 0;
+               if (pMsg != NULL)
+                       lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
+               return lRes;
+       }
+
+       LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lParam);
+       }
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(pMsg))
+                       return TRUE;
+               return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg);
+       }
+
+       HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD)
+       {
+               DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
+               DWORD dwExStyle = WS_EX_CLIENTEDGE;
+
+               CLIENTCREATESTRUCT ccs = { 0 };
+               ccs.hWindowMenu = hWindowMenu;
+               ccs.idFirstChild = nFirstChildID;
+
+               if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0)
+               {
+                       // parent MDI frame's scroll styles move to the MDICLIENT
+                       dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL));
+
+                       // fast way to turn off the scrollbar bits (without a resize)
+                       ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | SWP_FRAMECHANGED);
+               }
+
+               // Create MDICLIENT window
+               m_hWndClient = ::CreateWindowEx(dwExStyle, _T("MDIClient"), NULL,
+                       dwStyle, 0, 0, 1, 1, m_hWnd, (HMENU)LongToHandle(nID),
+                       ModuleHelper::GetModuleInstance(), (LPVOID)&ccs);
+               if (m_hWndClient == NULL)
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("MDI Frame failed to create MDICLIENT.\n"));
+                       return NULL;
+               }
+
+               // Move it to the top of z-order
+               ::BringWindowToTop(m_hWndClient);
+
+               // set as MDI client window
+               m_hWndMDIClient = m_hWndClient;
+
+               // update to proper size
+               T* pT = static_cast<T*>(this);
+               pT->UpdateLayout();
+
+               return m_hWndClient;
+       }
+
+       typedef CFrameWindowImplBase<TBase, TWinTraits >   _baseClass;
+
+       BEGIN_MSG_MAP(CMDIFrameWindowImpl)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+               MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
+#ifndef _ATL_NO_REBAR_SUPPORT
+#if (_WIN32_IE >= 0x0400)
+               NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
+#endif // (_WIN32_IE >= 0x0400)
+#if (_WIN32_IE >= 0x0500)
+               NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
+#endif // (_WIN32_IE >= 0x0500)
+#endif // !_ATL_NO_REBAR_SUPPORT
+               CHAIN_MSG_MAP(_baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(wParam != SIZE_MINIMIZED)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateLayout();
+               }
+               // message must be handled, otherwise DefFrameProc would resize the client again
+               return 0;
+       }
+
+       LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               // don't allow CFrameWindowImplBase to handle this one
+               return DefWindowProc(uMsg, wParam, lParam);
+       }
+
+       LRESULT OnMDISetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               SetMDIFrameMenu();
+               return 0;
+       }
+
+#ifndef _ATL_NO_REBAR_SUPPORT
+#if (_WIN32_IE >= 0x0400)
+       LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->UpdateLayout(FALSE);
+               return 0;
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500)
+       LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
+               if(!pT->PrepareChevronMenu(cmi))
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+               // display a popup menu with hidden items
+               pT->DisplayChevronMenu(cmi);
+               // cleanup
+               pT->CleanupChevronMenu(cmi);
+               return 0;
+       }
+#endif // (_WIN32_IE >= 0x0500)
+#endif // !_ATL_NO_REBAR_SUPPORT
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMDIChildWindowImpl
+
+#ifndef _WIN32_WCE
+
+template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CMDIChildWinTraits>
+class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
+{
+public:
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       UINT nMenuID = 0, LPVOID lpCreateParam = NULL)
+       {
+               ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
+
+               if(nMenuID != 0)
+                       m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nMenuID));
+
+               dwStyle = T::GetWndStyle(dwStyle);
+               dwExStyle = T::GetWndExStyle(dwExStyle);
+
+               dwExStyle |= WS_EX_MDICHILD;   // force this one
+               m_pfnSuperWindowProc = ::DefMDIChildProc;
+               m_hWndMDIClient = hWndParent;
+               ATLASSERT(::IsWindow(m_hWndMDIClient));
+
+               if(rect.m_lpRect == NULL)
+                       rect.m_lpRect = &TBase::rcDefault;
+
+               // If the currently active MDI child is maximized, we want to create this one maximized too
+               ATL::CWindow wndParent = hWndParent;
+               BOOL bMaximized = FALSE;
+               wndParent.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
+               if(bMaximized)
+                       wndParent.SetRedraw(FALSE);
+
+               HWND hWnd = CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCreateParam);
+
+               if(bMaximized)
+               {
+                       // Maximize and redraw everything
+                       if(hWnd != NULL)
+                               MDIMaximize(hWnd);
+                       wndParent.SetRedraw(TRUE);
+                       wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
+                       ::SetFocus(GetMDIFrame());   // focus will be set back to this window
+               }
+               else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(hWnd, ::GetFocus()))
+               {
+                       ::SetFocus(hWnd);
+               }
+
+               return hWnd;
+       }
+
+       HWND CreateEx(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR lpcstrWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
+       {
+               const int cchName = 256;
+               TCHAR szWindowName[cchName];
+               szWindowName[0] = 0;
+               if(lpcstrWindowName == NULL)
+               {
+                       ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
+                       lpcstrWindowName = szWindowName;
+               }
+
+               T* pT = static_cast<T*>(this);
+               HWND hWnd = pT->Create(hWndParent, rect, lpcstrWindowName, dwStyle, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam);
+
+               if(hWnd != NULL)
+                       m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
+
+               return hWnd;
+       }
+
+       BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               ATLASSERT(!::IsWindow(m_hWndToolBar));
+               if(nResourceID == 0)
+                       nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
+               m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
+               return (m_hWndToolBar != NULL);
+       }
+
+       BOOL UpdateClientEdge(LPRECT lpRect = NULL)
+       {
+               // only adjust for active MDI child window
+               HWND hWndChild = MDIGetActive();
+               if(hWndChild != NULL && hWndChild != m_hWnd)
+                       return FALSE;
+
+               // need to adjust the client edge style as max/restore happens
+               DWORD dwStyle = ::GetWindowLong(m_hWndMDIClient, GWL_EXSTYLE);
+               DWORD dwNewStyle = dwStyle;
+               if(hWndChild != NULL && ((GetExStyle() & WS_EX_CLIENTEDGE) == 0) && ((GetStyle() & WS_MAXIMIZE) != 0))
+                       dwNewStyle &= ~(WS_EX_CLIENTEDGE);
+               else
+                       dwNewStyle |= WS_EX_CLIENTEDGE;
+
+               if(dwStyle != dwNewStyle)
+               {
+                       // SetWindowPos will not move invalid bits
+                       ::RedrawWindow(m_hWndMDIClient, NULL, NULL,
+                               RDW_INVALIDATE | RDW_ALLCHILDREN);
+                       // remove/add WS_EX_CLIENTEDGE to MDI client area
+                       ::SetWindowLong(m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle);
+                       ::SetWindowPos(m_hWndMDIClient, NULL, 0, 0, 0, 0,
+                               SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE |
+                               SWP_NOZORDER | SWP_NOCOPYBITS);
+
+                       // return new client area
+                       if (lpRect != NULL)
+                               ::GetClientRect(m_hWndMDIClient, lpRect);
+
+                       return TRUE;
+               }
+
+               return FALSE;
+       }
+
+       typedef CFrameWindowImplBase<TBase, TWinTraits >   _baseClass;
+       BEGIN_MSG_MAP(CMDIChildWindowImpl)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)
+               MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
+               MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
+               MESSAGE_HANDLER(WM_MDIACTIVATE, OnMDIActivate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+#ifndef _ATL_NO_REBAR_SUPPORT
+#if (_WIN32_IE >= 0x0400)
+               NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
+#endif // (_WIN32_IE >= 0x0400)
+#if (_WIN32_IE >= 0x0500)
+               NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
+#endif // (_WIN32_IE >= 0x0500)
+#endif // !_ATL_NO_REBAR_SUPPORT
+               CHAIN_MSG_MAP(_baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               DefWindowProc(uMsg, wParam, lParam);   // needed for MDI children
+               if(wParam != SIZE_MINIMIZED)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateLayout();
+               }
+               return 0;
+       }
+
+       LRESULT OnWindowPosChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               // update MDI client edge and adjust MDI child rect
+               LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam;
+
+               if(!(lpWndPos->flags & SWP_NOSIZE))
+               {
+                       RECT rectClient;
+                       if(UpdateClientEdge(&rectClient) && ((GetStyle() & WS_MAXIMIZE) != 0))
+                       {
+                               ::AdjustWindowRectEx(&rectClient, GetStyle(), FALSE, GetExStyle());
+                               lpWndPos->x = rectClient.left;
+                               lpWndPos->y = rectClient.top;
+                               lpWndPos->cx = rectClient.right - rectClient.left;
+                               lpWndPos->cy = rectClient.bottom - rectClient.top;
+                       }
+               }
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);
+
+               // Activate this MDI window if needed
+               if(lRes == MA_ACTIVATE || lRes == MA_ACTIVATEANDEAT)
+               {
+                       if(MDIGetActive() != m_hWnd)
+                               MDIActivate(m_hWnd);
+               }
+
+               return lRes;
+       }
+
+       LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam);
+       }
+
+       LRESULT OnMDIActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if((HWND)lParam == m_hWnd && m_hMenu != NULL)
+                       SetMDIFrameMenu();
+               else if((HWND)lParam == NULL)
+                       ::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_hMenu != NULL)
+               {
+                       ::DestroyMenu(m_hMenu);
+                       m_hMenu = NULL;
+               }
+               UpdateClientEdge();
+               bHandled = FALSE;
+               return 1;
+       }
+
+#ifndef _ATL_NO_REBAR_SUPPORT
+#if (_WIN32_IE >= 0x0400)
+       LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->UpdateLayout(FALSE);
+               return 0;
+       }
+#endif // (_WIN32_IE >= 0x0400)
+
+#if (_WIN32_IE >= 0x0500)
+       LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
+               if(!pT->PrepareChevronMenu(cmi))
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+               // display a popup menu with hidden items
+               pT->DisplayChevronMenu(cmi);
+               // cleanup
+               pT->CleanupChevronMenu(cmi);
+               return 0;
+       }
+#endif // (_WIN32_IE >= 0x0500)
+#endif // !_ATL_NO_REBAR_SUPPORT
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// COwnerDraw - MI class for owner-draw support
+
+template <class T>
+class COwnerDraw
+{
+public:
+#if (_ATL_VER < 0x0700)
+       BOOL m_bHandledOD;
+
+       BOOL IsMsgHandled() const
+       {
+               return m_bHandledOD;
+       }
+       void SetMsgHandled(BOOL bHandled)
+       {
+               m_bHandledOD = bHandled;
+       }
+#endif // (_ATL_VER < 0x0700)
+
+// Message map and handlers
+       BEGIN_MSG_MAP(COwnerDraw< T >)
+               MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
+               MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
+               MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem)
+               MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem)
+       ALT_MSG_MAP(1)
+               MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)
+               MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem)
+               MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem)
+               MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem)
+       END_MSG_MAP()
+
+       LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetMsgHandled(TRUE);
+               pT->DrawItem((LPDRAWITEMSTRUCT)lParam);
+               bHandled = pT->IsMsgHandled();
+               return (LRESULT)TRUE;
+       }
+
+       LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetMsgHandled(TRUE);
+               pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam);
+               bHandled = pT->IsMsgHandled();
+               return (LRESULT)TRUE;
+       }
+
+       LRESULT OnCompareItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetMsgHandled(TRUE);
+               bHandled = pT->IsMsgHandled();
+               return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam);
+       }
+
+       LRESULT OnDeleteItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetMsgHandled(TRUE);
+               pT->DeleteItem((LPDELETEITEMSTRUCT)lParam);
+               bHandled = pT->IsMsgHandled();
+               return (LRESULT)TRUE;
+       }
+
+// Overrideables
+       void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/)
+       {
+               // must be implemented
+               ATLASSERT(FALSE);
+       }
+
+       void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
+       {
+               if(lpMeasureItemStruct->CtlType != ODT_MENU)
+               {
+                       // return default height for a system font
+                       T* pT = static_cast<T*>(this);
+                       HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID);
+                       CClientDC dc(hWnd);
+                       TEXTMETRIC tm = { 0 };
+                       dc.GetTextMetrics(&tm);
+
+                       lpMeasureItemStruct->itemHeight = tm.tmHeight;
+               }
+               else
+                       lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU);
+       }
+
+       int CompareItem(LPCOMPAREITEMSTRUCT /*lpCompareItemStruct*/)
+       {
+               // all items are equal
+               return 0;
+       }
+
+       void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/)
+       {
+               // default - nothing
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Update UI macros
+
+// these build the Update UI map inside a class definition
+#define BEGIN_UPDATE_UI_MAP(thisClass) \
+       static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \
+       { \
+               static const _AtlUpdateUIMap theMap[] = \
+               {
+
+#define UPDATE_ELEMENT(nID, wType) \
+                       { nID,  wType },
+
+#define END_UPDATE_UI_MAP() \
+                       { (WORD)-1, 0 } \
+               }; \
+               return theMap; \
+       }
+
+///////////////////////////////////////////////////////////////////////////////
+// CUpdateUI - manages UI elements updating
+
+class CUpdateUIBase
+{
+public:
+       // constants
+       enum
+       {
+               // UI element type
+               UPDUI_MENUPOPUP         = 0x0001,
+               UPDUI_MENUBAR           = 0x0002,
+               UPDUI_CHILDWINDOW       = 0x0004,
+               UPDUI_TOOLBAR           = 0x0008,
+               UPDUI_STATUSBAR         = 0x0010,
+               // state
+               UPDUI_ENABLED           = 0x0000,
+               UPDUI_DISABLED          = 0x0100,
+               UPDUI_CHECKED           = 0x0200,
+               UPDUI_CHECKED2          = 0x0400,
+               UPDUI_RADIO             = 0x0800,
+               UPDUI_DEFAULT           = 0x1000,
+               UPDUI_TEXT              = 0x2000,
+               // internal state
+               UPDUI_CLEARDEFAULT      = 0x4000,
+       };
+
+       // element data
+       struct _AtlUpdateUIElement
+       {
+               HWND m_hWnd;
+               WORD m_wType;
+
+               bool operator ==(const _AtlUpdateUIElement& e) const
+               { return (m_hWnd == e.m_hWnd && m_wType == e.m_wType); }
+       };
+
+       // map data
+       struct _AtlUpdateUIMap
+       {
+               WORD m_nID;
+               WORD m_wType;
+
+               bool operator ==(const _AtlUpdateUIMap& e) const
+               { return (m_nID == e.m_nID && m_wType == e.m_wType); }
+       };
+
+       // instance data
+       struct _AtlUpdateUIData
+       {
+               WORD m_wState;
+               union
+               {
+                       void* m_lpData;
+                       LPTSTR m_lpstrText;
+               };
+
+               bool operator ==(const _AtlUpdateUIData& e) const
+               { return (m_wState == e.m_wState && m_lpData == e.m_lpData); }
+       };
+
+       ATL::CSimpleArray<_AtlUpdateUIElement> m_UIElements;   // elements data
+       const _AtlUpdateUIMap* m_pUIMap;                       // static UI data
+       _AtlUpdateUIData* m_pUIData;                           // instance UI data
+       WORD m_wDirtyType;                                     // global dirty flag
+
+       bool m_bBlockAccelerators;
+
+
+// Constructor, destructor
+       CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0), m_bBlockAccelerators(false)
+       { }
+
+       ~CUpdateUIBase()
+       {
+               if(m_pUIMap != NULL && m_pUIData != NULL)
+               {
+                       const _AtlUpdateUIMap* pUIMap = m_pUIMap;
+                       _AtlUpdateUIData* pUIData = m_pUIData;
+                       while(pUIMap->m_nID != (WORD)-1)
+                       {
+                               if(pUIData->m_wState & UPDUI_TEXT)
+                                       delete [] pUIData->m_lpstrText;
+                               pUIMap++;
+                               pUIData++;
+                       }
+                       delete [] m_pUIData;
+               }
+       }
+
+// Check for disabled commands
+       bool UIGetBlockAccelerators() const
+       {
+               return m_bBlockAccelerators;
+       }
+
+       bool UISetBlockAccelerators(bool bBlock)
+       {
+               bool bOld = m_bBlockAccelerators;
+               m_bBlockAccelerators = bBlock;
+               return bOld;
+       }
+
+// Add elements
+       BOOL UIAddMenuBar(HWND hWnd)                // menu bar (main menu)
+       {
+               if(hWnd == NULL)
+                       return FALSE;
+               _AtlUpdateUIElement e;
+               e.m_hWnd = hWnd;
+               e.m_wType = UPDUI_MENUBAR;
+               return m_UIElements.Add(e);
+       }
+
+       BOOL UIAddToolBar(HWND hWnd)                // toolbar
+       {
+               if(hWnd == NULL)
+                       return FALSE;
+               _AtlUpdateUIElement e;
+               e.m_hWnd = hWnd;
+               e.m_wType = UPDUI_TOOLBAR;
+               return m_UIElements.Add(e);
+       }
+
+       BOOL UIAddStatusBar(HWND hWnd)              // status bar
+       {
+               if(hWnd == NULL)
+                       return FALSE;
+               _AtlUpdateUIElement e;
+               e.m_hWnd = hWnd;
+               e.m_wType = UPDUI_STATUSBAR;
+               return m_UIElements.Add(e);
+       }
+
+       BOOL UIAddChildWindowContainer(HWND hWnd)   // child window
+       {
+               if(hWnd == NULL)
+                       return FALSE;
+               _AtlUpdateUIElement e;
+               e.m_hWnd = hWnd;
+               e.m_wType = UPDUI_CHILDWINDOW;
+               return m_UIElements.Add(e);
+       }
+
+// Message map for popup menu updates and accelerator blocking
+       BEGIN_MSG_MAP(CUpdateUIBase)
+               MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
+               MESSAGE_HANDLER(WM_COMMAND, OnCommand)
+       END_MSG_MAP()
+
+       LRESULT OnInitMenuPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               bHandled = FALSE;
+               HMENU hMenu = (HMENU)wParam;
+               if(hMenu == NULL)
+                       return 1;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return 1;
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               while(pMap->m_nID != (WORD)-1)
+               {
+                       if(pMap->m_wType & UPDUI_MENUPOPUP)
+                               UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu);
+                       pMap++;
+                       pUIData++;
+               }
+               return 0;
+       }
+
+       LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               bHandled = FALSE;
+               if(m_bBlockAccelerators && HIWORD(wParam) == 1)   // accelerators only
+               {
+                       int nID = LOWORD(wParam);
+                       if((UIGetState(nID) & UPDUI_DISABLED) == UPDUI_DISABLED)
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIBase::OnCommand - blocked disabled command 0x%4.4X\n"), nID);
+                               bHandled = TRUE;   // eat the command, UI item is disabled
+                       }
+               }
+               return 0;
+       }
+
+// methods for setting UI element state
+       BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE)
+       {
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+
+               for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
+               {
+                       if(nID == (int)pMap->m_nID)
+                       {
+                               if(bEnable)
+                               {
+                                       if(pUIData->m_wState & UPDUI_DISABLED)
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState &= ~UPDUI_DISABLED;
+                                       }
+                               }
+                               else
+                               {
+                                       if(!(pUIData->m_wState & UPDUI_DISABLED))
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState |= UPDUI_DISABLED;
+                                       }
+                               }
+
+                               if(bForceUpdate)
+                                       pUIData->m_wState |= pMap->m_wType;
+                               if(pUIData->m_wState & pMap->m_wType)
+                                       m_wDirtyType |= pMap->m_wType;
+
+                               break;   // found
+                       }
+               }
+
+               return TRUE;
+       }
+
+       BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE)
+       {
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+
+               for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
+               {
+                       if(nID == (int)pMap->m_nID)
+                       {
+                               switch(nCheck)
+                               {
+                               case 0:
+                                       if((pUIData->m_wState & UPDUI_CHECKED) || (pUIData->m_wState & UPDUI_CHECKED2))
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState &= ~(UPDUI_CHECKED | UPDUI_CHECKED2);
+                                       }
+                                       break;
+                               case 1:
+                                       if(!(pUIData->m_wState & UPDUI_CHECKED))
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState &= ~UPDUI_CHECKED2;
+                                               pUIData->m_wState |= UPDUI_CHECKED;
+                                       }
+                                       break;
+                               case 2:
+                                       if(!(pUIData->m_wState & UPDUI_CHECKED2))
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState &= ~UPDUI_CHECKED;
+                                               pUIData->m_wState |= UPDUI_CHECKED2;
+                                       }
+                                       break;
+                               }
+
+                               if(bForceUpdate)
+                                       pUIData->m_wState |= pMap->m_wType;
+                               if(pUIData->m_wState & pMap->m_wType)
+                                       m_wDirtyType |= pMap->m_wType;
+
+                               break;   // found
+                       }
+               }
+
+               return TRUE;
+       }
+
+       // variant that supports bool (checked/not-checked, no intermediate state)
+       BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE)
+       {
+               return UISetCheck(nID, bCheck ? 1 : 0, bForceUpdate);
+       }
+
+       BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE)
+       {
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+
+               for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
+               {
+                       if(nID == (int)pMap->m_nID)
+                       {
+                               if(bRadio)
+                               {
+                                       if(!(pUIData->m_wState & UPDUI_RADIO))
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState |= UPDUI_RADIO;
+                                       }
+                               }
+                               else
+                               {
+                                       if(pUIData->m_wState & UPDUI_RADIO)
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState &= ~UPDUI_RADIO;
+                                       }
+                               }
+
+                               if(bForceUpdate)
+                                       pUIData->m_wState |= pMap->m_wType;
+                               if(pUIData->m_wState & pMap->m_wType)
+                                       m_wDirtyType |= pMap->m_wType;
+
+                               break;   // found
+                       }
+               }
+
+               return TRUE;
+       }
+
+       BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE)
+       {
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+               if(lpstrText == NULL)
+                       lpstrText = _T("");
+
+               for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
+               {
+                       if(nID == (int)pMap->m_nID)
+                       {
+                               if(pUIData->m_lpstrText == NULL || lstrcmp(pUIData->m_lpstrText, lpstrText))
+                               {
+                                       delete [] pUIData->m_lpstrText;
+                                       pUIData->m_lpstrText = NULL;
+                                       int nStrLen = lstrlen(lpstrText);
+                                       ATLTRY(pUIData->m_lpstrText = new TCHAR[nStrLen + 1]);
+                                       if(pUIData->m_lpstrText == NULL)
+                                       {
+                                               ATLTRACE2(atlTraceUI, 0, _T("UISetText - memory allocation failed\n"));
+                                               break;
+                                       }
+                                       SecureHelper::strcpy_x(pUIData->m_lpstrText, nStrLen + 1, lpstrText);
+                                       pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType);
+                               }
+
+                               if(bForceUpdate)
+                                       pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType);
+                               if(pUIData->m_wState & pMap->m_wType)
+                                       m_wDirtyType |= pMap->m_wType;
+
+                               break;   // found
+                       }
+               }
+
+               return TRUE;
+       }
+
+       BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE)
+       {
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+
+               for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
+               {
+                       if(nID == (int)pMap->m_nID)
+                       {
+                               if(bDefault)
+                               {
+                                       if((pUIData->m_wState & UPDUI_DEFAULT) == 0)
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState |= UPDUI_DEFAULT;
+                                       }
+                               }
+                               else
+                               {
+                                       if((pUIData->m_wState & UPDUI_DEFAULT) != 0)
+                                       {
+                                               pUIData->m_wState |= pMap->m_wType;
+                                               pUIData->m_wState &= ~UPDUI_DEFAULT;
+                                               pUIData->m_wState |= UPDUI_CLEARDEFAULT;
+                                       }
+                               }
+
+                               if(bForceUpdate)
+                                       pUIData->m_wState |= pMap->m_wType;
+                               if(pUIData->m_wState & pMap->m_wType)
+                                       m_wDirtyType |= pMap->m_wType;
+
+                               break;   // found
+                       }
+               }
+
+               return TRUE;
+       }
+
+// methods for complete state set/get
+       BOOL UISetState(int nID, DWORD dwState)
+       {
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+               for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
+               {
+                       if(nID == (int)pMap->m_nID)
+                       {               
+                               pUIData->m_wState = (WORD)(dwState | pMap->m_wType);
+                               m_wDirtyType |= pMap->m_wType;
+                               break;   // found
+                       }
+               }
+               return TRUE;
+       }
+
+       DWORD UIGetState(int nID)
+       {
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return 0;
+               for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
+               {
+                       if(nID == (int)pMap->m_nID)
+                               return pUIData->m_wState;
+               }
+               return 0;
+       }
+
+// methods for updating UI
+#ifndef _WIN32_WCE
+       BOOL UIUpdateMenuBar(BOOL bForceUpdate = FALSE, BOOL bMainMenu = FALSE)
+       {
+               if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate)
+                       return TRUE;
+
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+
+               while(pMap->m_nID != (WORD)-1)
+               {
+                       for(int i = 0; i < m_UIElements.GetSize(); i++)
+                       {
+                               if(m_UIElements[i].m_wType == UPDUI_MENUBAR)
+                               {
+                                       HMENU hMenu = ::GetMenu(m_UIElements[i].m_hWnd);
+                                       if(hMenu != NULL && (pUIData->m_wState & UPDUI_MENUBAR) && (pMap->m_wType & UPDUI_MENUBAR))
+                                               UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu);
+                               }
+                               if(bMainMenu)
+                                       ::DrawMenuBar(m_UIElements[i].m_hWnd);
+                       }
+                       pMap++;
+                       pUIData->m_wState &= ~UPDUI_MENUBAR;
+                       if(pUIData->m_wState & UPDUI_TEXT)
+                       {
+                               delete [] pUIData->m_lpstrText;
+                               pUIData->m_lpstrText = NULL;
+                               pUIData->m_wState &= ~UPDUI_TEXT;
+                       }
+                       pUIData++;
+               }
+
+               m_wDirtyType &= ~UPDUI_MENUBAR;
+               return TRUE;
+       }
+#endif // !_WIN32_WCE
+
+       BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE)
+       {
+               if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate)
+                       return TRUE;
+
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+
+               while(pMap->m_nID != (WORD)-1)
+               {
+                       for(int i = 0; i < m_UIElements.GetSize(); i++)
+                       {
+                               if(m_UIElements[i].m_wType == UPDUI_TOOLBAR)
+                               {
+                                       if((pUIData->m_wState & UPDUI_TOOLBAR) && (pMap->m_wType & UPDUI_TOOLBAR))
+                                               UIUpdateToolBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
+                               }
+                       }
+                       pMap++;
+                       pUIData->m_wState &= ~UPDUI_TOOLBAR;
+                       pUIData++;
+               }
+
+               m_wDirtyType &= ~UPDUI_TOOLBAR;
+               return TRUE;
+       }
+
+       BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE)
+       {
+               if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate)
+                       return TRUE;
+
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+
+               while(pMap->m_nID != (WORD)-1)
+               {
+                       for(int i = 0; i < m_UIElements.GetSize(); i++)
+                       {
+                               if(m_UIElements[i].m_wType == UPDUI_STATUSBAR)
+                               {
+                                       if((pUIData->m_wState & UPDUI_STATUSBAR) && (pMap->m_wType & UPDUI_STATUSBAR))
+                                               UIUpdateStatusBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
+                               }
+                       }
+                       pMap++;
+                       pUIData->m_wState &= ~UPDUI_STATUSBAR;
+                       if(pUIData->m_wState & UPDUI_TEXT)
+                       {
+                               delete [] pUIData->m_lpstrText;
+                               pUIData->m_lpstrText = NULL;
+                               pUIData->m_wState &= ~UPDUI_TEXT;
+                       }
+                       pUIData++;
+               }
+
+               m_wDirtyType &= ~UPDUI_STATUSBAR;
+               return TRUE;
+       }
+
+       BOOL UIUpdateChildWindows(BOOL bForceUpdate = FALSE)
+       {
+               if(!(m_wDirtyType & UPDUI_CHILDWINDOW) && !bForceUpdate)
+                       return TRUE;
+
+               const _AtlUpdateUIMap* pMap = m_pUIMap;
+               _AtlUpdateUIData* pUIData = m_pUIData;
+               if(pUIData == NULL)
+                       return FALSE;
+
+               while(pMap->m_nID != (WORD)-1)
+               {
+                       for(int i = 0; i < m_UIElements.GetSize(); i++)
+                       {
+                               if(m_UIElements[i].m_wType == UPDUI_CHILDWINDOW)
+                               {
+                                       if((pUIData->m_wState & UPDUI_CHILDWINDOW) && (pMap->m_wType & UPDUI_CHILDWINDOW))
+                                               UIUpdateChildWindow(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
+                               }
+                       }
+                       pMap++;
+                       pUIData->m_wState &= ~UPDUI_CHILDWINDOW;
+                       if(pUIData->m_wState & UPDUI_TEXT)
+                       {
+                               delete [] pUIData->m_lpstrText;
+                               pUIData->m_lpstrText = NULL;
+                               pUIData->m_wState &= ~UPDUI_TEXT;
+                       }
+                       pUIData++;
+               }
+
+               m_wDirtyType &= ~UPDUI_CHILDWINDOW;
+               return TRUE;
+       }
+
+// internal element specific methods
+       static void UIUpdateMenuBarElement(int nID, _AtlUpdateUIData* pUIData, HMENU hMenu)
+       {
+#ifndef _WIN32_WCE
+               if((pUIData->m_wState & UPDUI_CLEARDEFAULT) != 0)
+               {
+                       ::SetMenuDefaultItem(hMenu, (UINT)-1, 0);
+                       pUIData->m_wState &= ~UPDUI_CLEARDEFAULT;
+               }
+#endif // !_WIN32_WCE
+
+               CMenuItemInfo mii;
+               mii.fMask = MIIM_STATE;
+               mii.wID = nID;
+
+#ifndef _WIN32_WCE
+               if((pUIData->m_wState & UPDUI_DISABLED) != 0)
+                       mii.fState |= MFS_DISABLED | MFS_GRAYED;
+               else
+                       mii.fState |= MFS_ENABLED;
+
+               if((pUIData->m_wState & UPDUI_CHECKED) != 0)
+                       mii.fState |= MFS_CHECKED;
+               else
+                       mii.fState |= MFS_UNCHECKED;
+
+               if((pUIData->m_wState & UPDUI_DEFAULT) != 0)
+                       mii.fState |= MFS_DEFAULT;
+#else // CE specific
+               // ::SetMenuItemInfo() can't disable or check menu items
+               // on Windows CE, so we have to do that directly
+               UINT uEnable = MF_BYCOMMAND;
+               if((pUIData->m_wState & UPDUI_DISABLED) != 0)
+                       uEnable |= MF_GRAYED;
+               else
+                       uEnable |= MF_ENABLED;
+               ::EnableMenuItem(hMenu, nID, uEnable);
+
+               UINT uCheck = MF_BYCOMMAND;
+               if((pUIData->m_wState & UPDUI_CHECKED) != 0)
+                       uCheck |= MF_CHECKED;
+               else
+                       uCheck |= MF_UNCHECKED;
+               ::CheckMenuItem(hMenu, nID, uCheck);
+#endif // _WIN32_WCE
+
+               if((pUIData->m_wState & UPDUI_TEXT) != 0)
+               {
+                       CMenuItemInfo miiNow;
+                       miiNow.fMask = MIIM_TYPE;
+                       miiNow.wID = nID;
+                       if(::GetMenuItemInfo(hMenu, nID, FALSE, &miiNow))
+                       {
+                               mii.fMask |= MIIM_TYPE;
+                               // MFT_BITMAP and MFT_SEPARATOR don't go together with MFT_STRING
+#ifndef _WIN32_WCE
+                               mii.fType |= (miiNow.fType & ~(MFT_BITMAP | MFT_SEPARATOR)) | MFT_STRING;
+#else // CE specific
+                               mii.fType |= (miiNow.fType & ~(MFT_SEPARATOR)) | MFT_STRING;
+#endif // _WIN32_WCE
+                               mii.dwTypeData = pUIData->m_lpstrText;
+                       }
+               }
+
+               ::SetMenuItemInfo(hMenu, nID, FALSE, &mii);
+       }
+
+       static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndToolBar)
+       {
+               // Note: only handles enabled/disabled, checked state, and radio (press)
+               ::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
+               ::SendMessage(hWndToolBar, TB_CHECKBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED) ? TRUE : FALSE);
+               ::SendMessage(hWndToolBar, TB_INDETERMINATE, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE);
+               ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_RADIO) ? TRUE : FALSE);
+       }
+
+       static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndStatusBar)
+       {
+               // Note: only handles text
+               if(pUIData->m_wState & UPDUI_TEXT)
+                       ::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pUIData->m_lpstrText);
+       }
+
+       static void UIUpdateChildWindow(int nID, _AtlUpdateUIData* pUIData, HWND hWnd)
+       {
+               HWND hChild = ::GetDlgItem(hWnd, nID);
+
+               ::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
+               // for check and radio, assume that window is a button
+               int nCheck = BST_UNCHECKED;
+               if(pUIData->m_wState & UPDUI_CHECKED || pUIData->m_wState & UPDUI_RADIO)
+                       nCheck = BST_CHECKED;
+               else if(pUIData->m_wState & UPDUI_CHECKED2)
+                       nCheck = BST_INDETERMINATE;
+               ::SendMessage(hChild, BM_SETCHECK, nCheck, 0L);
+               if(pUIData->m_wState & UPDUI_DEFAULT)
+               {
+                       DWORD dwRet = (DWORD)::SendMessage(hWnd, DM_GETDEFID, 0, 0L);
+                       if(HIWORD(dwRet) == DC_HASDEFID)
+                       {
+                               HWND hOldDef = ::GetDlgItem(hWnd, (int)(short)LOWORD(dwRet));
+                               // remove BS_DEFPUSHBUTTON
+                               ::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
+                       }
+                       ::SendMessage(hWnd, DM_SETDEFID, nID, 0L);
+               }
+               if(pUIData->m_wState & UPDUI_TEXT)
+                       ::SetWindowText(hChild, pUIData->m_lpstrText);
+       }
+};
+
+template <class T>
+class CUpdateUI : public CUpdateUIBase
+{
+public:
+       CUpdateUI()
+       {
+               T* pT = static_cast<T*>(this);
+               pT;
+               const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
+               m_pUIMap = pMap;
+               ATLASSERT(m_pUIMap != NULL);
+               int nCount;
+               for(nCount = 1; pMap->m_nID != (WORD)-1; nCount++)
+                       pMap++;
+
+               // check for duplicates (debug only)
+#ifdef _DEBUG
+               for(int i = 0; i < nCount; i++)
+               {
+                       for(int j = 0; j < nCount; j++)
+                       {
+                               // shouldn't have duplicates in the update UI map
+                               if(i != j)
+                                       ATLASSERT(m_pUIMap[j].m_nID != m_pUIMap[i].m_nID);
+                       }
+               }
+#endif // _DEBUG
+
+               ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]);
+               ATLASSERT(m_pUIData != NULL);
+
+               if(m_pUIData != NULL)
+                       memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDynamicUpdateUI - allows update elements to dynamically added and removed
+//                    in addition to a static update UI map
+
+template <class T>
+class CDynamicUpdateUI : public CUpdateUIBase
+{
+public:
+// Data members
+       ATL::CSimpleArray<_AtlUpdateUIMap> m_arrUIMap;     // copy of the static UI data
+       ATL::CSimpleArray<_AtlUpdateUIData> m_arrUIData;   // instance UI data
+
+// Constructor/destructor
+       CDynamicUpdateUI()
+       {
+               T* pT = static_cast<T*>(this);
+               pT;
+               const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
+               ATLASSERT(pMap != NULL);
+
+               for(;;)
+               {
+                       BOOL bRet = m_arrUIMap.Add(*(_AtlUpdateUIMap*)pMap);
+                       ATLASSERT(bRet);
+
+                       if(bRet != FALSE)
+                       {
+                               _AtlUpdateUIData data = { 0, NULL };
+                               bRet = m_arrUIData.Add(data);
+                               ATLASSERT(bRet);
+                       }
+
+                       if(pMap->m_nID == (WORD)-1)
+                               break;
+
+                       pMap++;
+               }
+
+               ATLASSERT(m_arrUIMap.GetSize() == m_arrUIData.GetSize());
+
+#ifdef _DEBUG
+               // check for duplicates (debug only)
+               for(int i = 0; i < m_arrUIMap.GetSize(); i++)
+               {
+                       for(int j = 0; j < m_arrUIMap.GetSize(); j++)
+                       {
+                               // shouldn't have duplicates in the update UI map
+                               if(i != j)
+                                       ATLASSERT(m_arrUIMap[j].m_nID != m_arrUIMap[i].m_nID);
+                       }
+               }
+#endif // _DEBUG
+
+               // Set internal data pointers to point to the new data arrays
+               m_pUIMap = m_arrUIMap.m_aT;
+               m_pUIData = m_arrUIData.m_aT;
+       }
+
+       ~CDynamicUpdateUI()
+       {
+               for(int i = 0; i < m_arrUIData.GetSize(); i++)
+               {
+                       if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0)
+                               delete [] m_arrUIData[i].m_lpstrText;
+               }
+
+               // Reset internal data pointers (memory will be released by CSimpleArray d-tor)
+               m_pUIMap = NULL;
+               m_pUIData = NULL;
+       }
+
+// Methods for dynamically adding and removing update elements
+       bool UIAddUpdateElement(WORD nID, WORD wType)
+       {
+               // check for duplicates
+               for(int i = 0; i < m_arrUIMap.GetSize(); i++)
+               {
+                       // shouldn't have duplicates in the update UI map
+                       ATLASSERT(m_arrUIMap[i].m_nID != nID);
+                       if(m_arrUIMap[i].m_nID == nID)
+                               return false;
+               }
+
+               bool bRetVal = false;
+
+               // Add new end element
+               _AtlUpdateUIMap uumEnd = { (WORD)-1, 0 };
+               BOOL bRet = m_arrUIMap.Add(uumEnd);
+               ATLASSERT(bRet);
+
+               if(bRet != FALSE)
+               {
+                       _AtlUpdateUIData uud = { 0, NULL };
+                       bRet = m_arrUIData.Add(uud);
+                       ATLASSERT(bRet);
+
+                       // Set new data to the previous end element
+                       if(bRet != FALSE)
+                       {
+                               int nSize = m_arrUIMap.GetSize();
+                               _AtlUpdateUIMap uum = { nID, wType };
+                               m_arrUIMap.SetAtIndex(nSize - 2, uum);
+                               m_arrUIData.SetAtIndex(nSize - 2, uud);
+
+                               // Set internal data pointers again, just in case that memory moved
+                               m_pUIMap = m_arrUIMap.m_aT;
+                               m_pUIData = m_arrUIData.m_aT;
+
+                               bRetVal = true;
+                       }
+               }
+
+               return bRetVal;
+       }
+
+       bool UIRemoveUpdateElement(WORD nID)
+       {
+               bool bRetVal = false;
+
+               for(int i = 0; i < m_arrUIMap.GetSize(); i++)
+               {
+                       if(m_arrUIMap[i].m_nID == nID)
+                       {
+                               BOOL bRet = m_arrUIMap.RemoveAt(i);
+                               ATLASSERT(bRet);
+                               bRet = m_arrUIData.RemoveAt(i);
+                               ATLASSERT(bRet);
+
+                               bRetVal = true;
+                               break;
+                       }
+               }
+
+               return bRetVal;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDialogResize - provides support for resizing dialog controls
+//                 (works for any window that has child controls)
+
+// Put CDialogResize in the list of base classes for a dialog (or even plain window),
+// then implement DLGRESIZE map by specifying controls and groups of control
+// and using DLSZ_* values to specify how are they supposed to be resized.
+//
+// Notes:
+// - Resizeable border (WS_THICKFRAME style) should be set in the dialog template
+//   for top level dialogs (popup or overlapped), so that users can resize the dialog.
+// - Some flags cannot be combined; for instance DLSZ_CENTER_X overrides DLSZ_SIZE_X,
+//   DLSZ_SIZE_X overrides DLSZ_MOVE_X. X and Y flags can be combined.
+// - Order of controls is important - group controls are resized and moved based
+//   on the position of the previous control in a group.
+
+// dialog resize map macros
+#define BEGIN_DLGRESIZE_MAP(thisClass) \
+       static const _AtlDlgResizeMap* GetDlgResizeMap() \
+       { \
+               static const _AtlDlgResizeMap theMap[] = \
+               {
+
+#define END_DLGRESIZE_MAP() \
+                       { -1, 0 }, \
+               }; \
+               return theMap; \
+       }
+
+#define DLGRESIZE_CONTROL(id, flags) \
+               { id, flags },
+
+#define BEGIN_DLGRESIZE_GROUP() \
+               { -1, _DLSZ_BEGIN_GROUP },
+
+#define END_DLGRESIZE_GROUP() \
+               { -1, _DLSZ_END_GROUP },
+
+
+template <class T>
+class CDialogResize
+{
+public:
+// Data declarations and members
+       enum
+       {
+               DLSZ_SIZE_X             = 0x00000001,
+               DLSZ_SIZE_Y             = 0x00000002,
+               DLSZ_MOVE_X             = 0x00000004,
+               DLSZ_MOVE_Y             = 0x00000008,
+               DLSZ_REPAINT            = 0x00000010,
+               DLSZ_CENTER_X           = 0x00000020,
+               DLSZ_CENTER_Y           = 0x00000040,
+
+               // internal use only
+               _DLSZ_BEGIN_GROUP       = 0x00001000,
+               _DLSZ_END_GROUP         = 0x00002000,
+               _DLSZ_GRIPPER           = 0x00004000
+       };
+
+       struct _AtlDlgResizeMap
+       {
+               int m_nCtlID;
+               DWORD m_dwResizeFlags;
+       };
+
+       struct _AtlDlgResizeData
+       {
+               int m_nCtlID;
+               DWORD m_dwResizeFlags;
+               RECT m_rect;
+
+               int GetGroupCount() const
+               {
+                       return (int)LOBYTE(HIWORD(m_dwResizeFlags));
+               }
+
+               void SetGroupCount(int nCount)
+               {
+                       ATLASSERT(nCount > 0 && nCount < 256);
+                       DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0));
+                       m_dwResizeFlags &= 0xFF00FFFF;
+                       m_dwResizeFlags |= dwCount;
+               }
+
+               bool operator ==(const _AtlDlgResizeData& r) const
+               { return (m_nCtlID == r.m_nCtlID && m_dwResizeFlags == r.m_dwResizeFlags); }
+       };
+
+       ATL::CSimpleArray<_AtlDlgResizeData> m_arrData;
+       SIZE m_sizeDialog;
+       POINT m_ptMinTrackSize;
+       bool m_bGripper;
+
+
+// Constructor
+       CDialogResize() : m_bGripper(false)
+       {
+               m_sizeDialog.cx = 0;
+               m_sizeDialog.cy = 0;
+               m_ptMinTrackSize.x = -1;
+               m_ptMinTrackSize.y = -1;
+       }
+
+// Operations
+       void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = true, DWORD dwForceStyle = WS_CLIPCHILDREN)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               DWORD dwStyle = pT->GetStyle();
+
+#ifdef _DEBUG
+               // Debug only: Check if top level dialogs have a resizeable border.
+               if(((dwStyle & WS_CHILD) == 0) && ((dwStyle & WS_THICKFRAME) == 0))
+                       ATLTRACE2(atlTraceUI, 0, _T("DlgResize_Init - warning: top level dialog without the WS_THICKFRAME style - user cannot resize it\n"));
+#endif // _DEBUG
+
+               // Force specified styles (default WS_CLIPCHILDREN reduces flicker)
+               if((dwStyle & dwForceStyle) != dwForceStyle)
+                       pT->ModifyStyle(0, dwForceStyle);
+
+               // Adding this style removes an empty icon that dialogs with WS_THICKFRAME have.
+               // Setting icon to NULL is required when XP themes are active.
+               // Note: This will not prevent adding an icon for the dialog using SetIcon()
+               if((dwStyle & WS_CHILD) == 0)
+               {
+                       pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME);
+                       if(pT->GetIcon(FALSE) == NULL)
+                               pT->SetIcon(NULL, FALSE);
+               }
+
+               // Cleanup in case of multiple initialization
+               // block: first check for the gripper control, destroy it if needed
+               {
+                       ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
+                       if(wndGripper.IsWindow() && m_arrData.GetSize() > 0 && (m_arrData[0].m_dwResizeFlags & _DLSZ_GRIPPER) != 0)
+                               wndGripper.DestroyWindow();
+               }
+               // clear out everything else
+               m_arrData.RemoveAll();
+               m_sizeDialog.cx = 0;
+               m_sizeDialog.cy = 0;
+               m_ptMinTrackSize.x = -1;
+               m_ptMinTrackSize.y = -1;
+
+               // Get initial dialog client size
+               RECT rectDlg = { 0 };
+               pT->GetClientRect(&rectDlg);
+               m_sizeDialog.cx = rectDlg.right;
+               m_sizeDialog.cy = rectDlg.bottom;
+
+#ifndef _WIN32_WCE
+               // Create gripper if requested
+               m_bGripper = false;
+               if(bAddGripper)
+               {
+                       // shouldn't exist already
+                       ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)));
+                       if(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)))
+                       {
+                               ATL::CWindow wndGripper;
+                               wndGripper.Create(_T("SCROLLBAR"), pT->m_hWnd, rectDlg, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEBOX | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN, 0, ATL_IDW_STATUS_BAR);
+                               ATLASSERT(wndGripper.IsWindow());
+                               if(wndGripper.IsWindow())
+                               {
+                                       m_bGripper = true;
+                                       RECT rectCtl = { 0 };
+                                       wndGripper.GetWindowRect(&rectCtl);
+                                       ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
+                                       _AtlDlgResizeData data = { ATL_IDW_STATUS_BAR, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | _DLSZ_GRIPPER, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } };
+                                       m_arrData.Add(data);
+                               }
+                       }
+               }
+#else // CE specific
+               bAddGripper;   // avoid level 4 warning
+#endif // _WIN32_WCE
+
+               // Get min track position if requested
+               if(bUseMinTrackSize)
+               {
+                       if((dwStyle & WS_CHILD) != 0)
+                       {
+                               RECT rect = { 0 };
+                               pT->GetClientRect(&rect);
+                               m_ptMinTrackSize.x = rect.right - rect.left;
+                               m_ptMinTrackSize.y = rect.bottom - rect.top;
+                       }
+                       else
+                       {
+                               RECT rect = { 0 };
+                               pT->GetWindowRect(&rect);
+                               m_ptMinTrackSize.x = rect.right - rect.left;
+                               m_ptMinTrackSize.y = rect.bottom - rect.top;
+                       }
+               }
+
+               // Walk the map and initialize data
+               const _AtlDlgResizeMap* pMap = pT->GetDlgResizeMap();
+               ATLASSERT(pMap != NULL);
+               int nGroupStart = -1;
+               for(int nCount = 1; !(pMap->m_nCtlID == -1 && pMap->m_dwResizeFlags == 0); nCount++, pMap++)
+               {
+                       if(pMap->m_nCtlID == -1)
+                       {
+                               switch(pMap->m_dwResizeFlags)
+                               {
+                               case _DLSZ_BEGIN_GROUP:
+                                       ATLASSERT(nGroupStart == -1);
+                                       nGroupStart = m_arrData.GetSize();
+                                       break;
+                               case _DLSZ_END_GROUP:
+                                       {
+                                               ATLASSERT(nGroupStart != -1);
+                                               int nGroupCount = m_arrData.GetSize() - nGroupStart;
+                                               m_arrData[nGroupStart].SetGroupCount(nGroupCount);
+                                               nGroupStart = -1;
+                                       }
+                                       break;
+                               default:
+                                       ATLASSERT(FALSE && _T("Invalid DLGRESIZE Map Entry"));
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               // this ID conflicts with the default gripper one
+                               ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_IDW_STATUS_BAR) : TRUE);
+
+                               ATL::CWindow ctl = pT->GetDlgItem(pMap->m_nCtlID);
+                               ATLASSERT(ctl.IsWindow());
+                               RECT rectCtl = { 0 };
+                               ctl.GetWindowRect(&rectCtl);
+                               ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
+
+                               DWORD dwGroupFlag = (nGroupStart != -1 && m_arrData.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0;
+                               _AtlDlgResizeData data = { pMap->m_nCtlID, pMap->m_dwResizeFlags | dwGroupFlag, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } };
+                               m_arrData.Add(data);
+                       }
+               }
+               ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the DLGRESIZE Map"));
+       }
+
+       void DlgResize_UpdateLayout(int cxWidth, int cyHeight)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               // Restrict minimum size if requested
+               if(((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
+               {
+                       if(cxWidth < m_ptMinTrackSize.x)
+                               cxWidth = m_ptMinTrackSize.x;
+                       if(cyHeight < m_ptMinTrackSize.y)
+                               cyHeight = m_ptMinTrackSize.y;
+               }
+
+               BOOL bVisible = pT->IsWindowVisible();
+               if(bVisible)
+                       pT->SetRedraw(FALSE);
+
+               for(int i = 0; i < m_arrData.GetSize(); i++)
+               {
+                       if((m_arrData[i].m_dwResizeFlags & _DLSZ_BEGIN_GROUP) != 0)   // start of a group
+                       {
+                               int nGroupCount = m_arrData[i].GetGroupCount();
+                               ATLASSERT(nGroupCount > 0 && i + nGroupCount - 1 < m_arrData.GetSize());
+                               RECT rectGroup = m_arrData[i].m_rect;
+
+                               int j = 1;
+                               for(j = 1; j < nGroupCount; j++)
+                               {
+                                       rectGroup.left = min(rectGroup.left, m_arrData[i + j].m_rect.left);
+                                       rectGroup.top = min(rectGroup.top, m_arrData[i + j].m_rect.top);
+                                       rectGroup.right = max(rectGroup.right, m_arrData[i + j].m_rect.right);
+                                       rectGroup.bottom = max(rectGroup.bottom, m_arrData[i + j].m_rect.bottom);
+                               }
+
+                               for(j = 0; j < nGroupCount; j++)
+                               {
+                                       _AtlDlgResizeData* pDataPrev = NULL;
+                                       if(j > 0)
+                                               pDataPrev = &(m_arrData[i + j - 1]);
+                                       pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i + j], true, pDataPrev);
+                               }
+
+                               i += nGroupCount - 1;   // increment to skip all group controls
+                       }
+                       else // one control entry
+                       {
+                               RECT rectGroup = { 0, 0, 0, 0 };
+                               pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i], false);
+                       }
+               }
+
+               if(bVisible)
+                       pT->SetRedraw(TRUE);
+
+               pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CDialogResize)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo)
+#endif // _WIN32_WCE
+       END_MSG_MAP()
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+#ifndef _WIN32_WCE
+               if(m_bGripper)
+               {
+                       ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
+                       if(wParam == SIZE_MAXIMIZED)
+                               wndGripper.ShowWindow(SW_HIDE);
+                       else if(wParam == SIZE_RESTORED)
+                               wndGripper.ShowWindow(SW_SHOW);
+               }
+#endif // _WIN32_WCE
+               if(wParam != SIZE_MINIMIZED)
+               {
+                       ATLASSERT(::IsWindow(pT->m_hWnd));
+                       pT->DlgResize_UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+               }
+               return 0;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               if(m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
+               {
+                       LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
+                       lpMMI->ptMinTrackSize =  m_ptMinTrackSize;
+               }
+               return 0;
+       }
+#endif // _WIN32_WCE
+
+// Implementation
+       bool DlgResize_PositionControl(int cxWidth, int cyHeight, RECT& rectGroup, _AtlDlgResizeData& data, bool bGroup, 
+                                      _AtlDlgResizeData* pDataPrev = NULL)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               ATL::CWindow ctl;
+               RECT rectCtl = { 0 };
+
+               ctl = pT->GetDlgItem(data.m_nCtlID);
+               if(!ctl.GetWindowRect(&rectCtl))
+                       return false;
+               ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
+
+               if(bGroup)
+               {
+                       if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0)
+                       {
+                               int cxRight = rectGroup.right + cxWidth - m_sizeDialog.cx;
+                               int cxCtl = data.m_rect.right - data.m_rect.left;
+                               rectCtl.left = rectGroup.left + (cxRight - rectGroup.left - cxCtl) / 2;
+                               rectCtl.right = rectCtl.left + cxCtl;
+                       }
+                       else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0)
+                       {
+                               rectCtl.left = rectGroup.left + ::MulDiv(data.m_rect.left - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left);
+
+                               if((data.m_dwResizeFlags & DLSZ_SIZE_X) != 0)
+                               {
+                                       rectCtl.right = rectGroup.left + ::MulDiv(data.m_rect.right - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left);
+
+                                       if(pDataPrev != NULL)
+                                       {
+                                               ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID);
+                                               RECT rcPrev = { 0 };
+                                               ctlPrev.GetWindowRect(&rcPrev);
+                                               ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
+                                               int dxAdjust = (rectCtl.left - rcPrev.right) - (data.m_rect.left - pDataPrev->m_rect.right);
+                                               rcPrev.right += dxAdjust;
+                                               ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
+                                       }
+                               }
+                               else
+                               {
+                                       rectCtl.right = rectCtl.left + (data.m_rect.right - data.m_rect.left);
+                               }
+                       }
+
+                       if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0)
+                       {
+                               int cyBottom = rectGroup.bottom + cyHeight - m_sizeDialog.cy;
+                               int cyCtl = data.m_rect.bottom - data.m_rect.top;
+                               rectCtl.top = rectGroup.top + (cyBottom - rectGroup.top - cyCtl) / 2;
+                               rectCtl.bottom = rectCtl.top + cyCtl;
+                       }
+                       else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0)
+                       {
+                               rectCtl.top = rectGroup.top + ::MulDiv(data.m_rect.top - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top);
+
+                               if((data.m_dwResizeFlags & DLSZ_SIZE_Y) != 0)
+                               {
+                                       rectCtl.bottom = rectGroup.top + ::MulDiv(data.m_rect.bottom - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top);
+
+                                       if(pDataPrev != NULL)
+                                       {
+                                               ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID);
+                                               RECT rcPrev = { 0 };
+                                               ctlPrev.GetWindowRect(&rcPrev);
+                                               ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
+                                               int dxAdjust = (rectCtl.top - rcPrev.bottom) - (data.m_rect.top - pDataPrev->m_rect.bottom);
+                                               rcPrev.bottom += dxAdjust;
+                                               ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
+                                       }
+                               }
+                               else
+                               {
+                                       rectCtl.bottom = rectCtl.top + (data.m_rect.bottom - data.m_rect.top);
+                               }
+                       }
+               }
+               else // no group
+               {
+                       if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0)
+                       {
+                               int cxCtl = data.m_rect.right - data.m_rect.left;
+                               rectCtl.left = (cxWidth - cxCtl) / 2;
+                               rectCtl.right = rectCtl.left + cxCtl;
+                       }
+                       else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0)
+                       {
+                               rectCtl.right = data.m_rect.right + (cxWidth - m_sizeDialog.cx);
+
+                               if((data.m_dwResizeFlags & DLSZ_MOVE_X) != 0)
+                                       rectCtl.left = rectCtl.right - (data.m_rect.right - data.m_rect.left);
+                       }
+
+                       if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0)
+                       {
+                               int cyCtl = data.m_rect.bottom - data.m_rect.top;
+                               rectCtl.top = (cyHeight - cyCtl) / 2;
+                               rectCtl.bottom = rectCtl.top + cyCtl;
+                       }
+                       else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0)
+                       {
+                               rectCtl.bottom = data.m_rect.bottom + (cyHeight - m_sizeDialog.cy);
+
+                               if((data.m_dwResizeFlags & DLSZ_MOVE_Y) != 0)
+                                       rectCtl.top = rectCtl.bottom - (data.m_rect.bottom - data.m_rect.top);
+                       }
+               }
+
+               if((data.m_dwResizeFlags & DLSZ_REPAINT) != 0)
+                       ctl.Invalidate();
+
+               if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | DLSZ_CENTER_X | DLSZ_CENTER_Y)) != 0)
+                       ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOACTIVATE);
+
+               return true;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDoubleBufferImpl - Provides double-buffer painting support to any window
+
+template <class T>
+class CDoubleBufferImpl
+{
+public:
+// Overrideables
+       void DoPaint(CDCHandle /*dc*/)
+       {
+               // must be implemented in a derived class
+               ATLASSERT(FALSE);
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CDoubleBufferImpl)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+#endif // !_WIN32_WCE
+       END_MSG_MAP()
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;   // no background painting needed
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               if(wParam != NULL)
+               {
+                       RECT rect = { 0 };
+                       pT->GetClientRect(&rect);
+                       CMemoryDC dcMem((HDC)wParam, rect);
+                       pT->DoPaint(dcMem.m_hDC);
+               }
+               else
+               {
+                       CPaintDC dc(pT->m_hWnd);
+                       CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint);
+                       pT->DoPaint(dcMem.m_hDC);
+               }
+
+               return 0;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDoubleBufferWindowImpl - Implements a double-buffer painting window
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CDoubleBufferWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CDoubleBufferImpl< T >
+{
+public:
+       BEGIN_MSG_MAP(CDoubleBufferWindowImpl)
+               CHAIN_MSG_MAP(CDoubleBufferImpl< T >)
+       END_MSG_MAP()
+};
+
+
+// command bar support
+#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
+  #undef CBRM_GETMENU
+  #undef CBRM_TRACKPOPUPMENU
+  #undef CBRM_GETCMDBAR
+  #undef CBRPOPUPMENU
+#endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
+
+}; // namespace WTL
+
+#endif // __ATLFRAME_H__
diff --git a/include/WTL/Include/atlgdi.h b/include/WTL/Include/atlgdi.h
new file mode 100644 (file)
index 0000000..c6f8019
--- /dev/null
@@ -0,0 +1,3850 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLGDI_H__
+#define __ATLGDI_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlgdi.h requires atlapp.h to be included first
+#endif
+
+
+// protect template members from windowsx.h macros
+#ifdef _INC_WINDOWSX
+  #undef CopyRgn
+  #undef CreateBrush
+  #undef CreatePen
+  #undef SelectBrush
+  #undef SelectPen
+  #undef SelectFont
+  #undef SelectBitmap
+#endif // _INC_WINDOWSX
+
+// required libraries
+#if !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE)
+  #pragma comment(lib, "msimg32.lib")
+#endif // !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE)
+#if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE)
+  #pragma comment(lib, "opengl32.lib")
+#endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CPenT<t_bManaged>
+// CBrushT<t_bManaged>
+// CLogFont
+// CFontT<t_bManaged>
+// CBitmapT<t_bManaged>
+// CPaletteT<t_bManaged>
+// CRgnT<t_bManaged>
+// CDCT<t_bManaged>
+// CPaintDC
+// CClientDC
+// CWindowDC
+// CMemoryDC
+// CEnhMetaFileInfo
+// CEnhMetaFileT<t_bManaged>
+// CEnhMetaFileDC
+//
+// Global functions:
+//   AtlGetBitmapResourceInfo()
+//   AtlGetBitmapResourceBitsPerPixel()
+//   AtlIsAlphaBitmapResource()
+//   AtlIsDib16()
+//   AtlGetDibColorTableSize()
+//   AtlGetDibNumColors(),
+//   AtlGetDibBitmap()
+//   AtlCopyBitmap()
+//   AtlCreatePackedDib16()
+//   AtlSetClipboardDib16()
+//   AtlGetClipboardDib()
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// Bitmap resource helpers to extract bitmap information for a bitmap resource
+
+inline LPBITMAPINFOHEADER AtlGetBitmapResourceInfo(HMODULE hModule, ATL::_U_STRINGorID image)
+{
+       HRSRC hResource = ::FindResource(hModule, image.m_lpstr, RT_BITMAP);
+       ATLASSERT(hResource != NULL);
+       HGLOBAL hGlobal = ::LoadResource(hModule, hResource);
+       ATLASSERT(hGlobal != NULL);
+       LPBITMAPINFOHEADER pBitmapInfoHeader = (LPBITMAPINFOHEADER)::LockResource(hGlobal);
+       ATLASSERT(pBitmapInfoHeader != NULL);
+       return pBitmapInfoHeader;
+}
+
+inline WORD AtlGetBitmapResourceBitsPerPixel(HMODULE hModule, ATL::_U_STRINGorID image)
+{
+       LPBITMAPINFOHEADER pBitmapInfoHeader = AtlGetBitmapResourceInfo(hModule, image);
+       ATLASSERT(pBitmapInfoHeader != NULL);
+       return pBitmapInfoHeader->biBitCount;
+}
+
+inline WORD AtlGetBitmapResourceBitsPerPixel(ATL::_U_STRINGorID image)
+{
+       return AtlGetBitmapResourceBitsPerPixel(ModuleHelper::GetResourceInstance(), image);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// 32-bit (alpha channel) bitmap resource helper
+
+// Note: 32-bit (alpha channel) images work only on Windows XP with Common Controls version 6.
+// If you want your app to work on older version of Windows, load non-alpha images if Common
+// Controls version is less than 6.
+
+inline bool AtlIsAlphaBitmapResource(ATL::_U_STRINGorID image)
+{
+       return (AtlGetBitmapResourceBitsPerPixel(image) == 32);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPen
+
+template <bool t_bManaged>
+class CPenT
+{
+public:
+// Data members
+       HPEN m_hPen;
+
+// Constructor/destructor/operators
+       CPenT(HPEN hPen = NULL) : m_hPen(hPen)
+       { }
+
+       ~CPenT()
+       {
+               if(t_bManaged && m_hPen != NULL)
+                       DeleteObject();
+       }
+
+       CPenT<t_bManaged>& operator =(HPEN hPen)
+       {
+               Attach(hPen);
+               return *this;
+       }
+
+       void Attach(HPEN hPen)
+       {
+               if(t_bManaged && m_hPen != NULL && m_hPen != hPen)
+                       ::DeleteObject(m_hPen);
+               m_hPen = hPen;
+       }
+
+       HPEN Detach()
+       {
+               HPEN hPen = m_hPen;
+               m_hPen = NULL;
+               return hPen;
+       }
+
+       operator HPEN() const { return m_hPen; }
+
+       bool IsNull() const { return (m_hPen == NULL); }
+
+// Create methods
+       HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor)
+       {
+               ATLASSERT(m_hPen == NULL);
+               m_hPen = ::CreatePen(nPenStyle, nWidth, crColor);
+               return m_hPen;
+       }
+
+#ifndef _WIN32_WCE
+       HPEN CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL)
+       {
+               ATLASSERT(m_hPen == NULL);
+               m_hPen = ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle);
+               return m_hPen;
+       }
+#endif // !_WIN32_WCE
+
+       HPEN CreatePenIndirect(LPLOGPEN lpLogPen)
+       {
+               ATLASSERT(m_hPen == NULL);
+               m_hPen = ::CreatePenIndirect(lpLogPen);
+               return m_hPen;
+       }
+
+       BOOL DeleteObject()
+       {
+               ATLASSERT(m_hPen != NULL);
+               BOOL bRet = ::DeleteObject(m_hPen);
+               if(bRet)
+                       m_hPen = NULL;
+               return bRet;
+       }
+
+// Attributes
+       int GetLogPen(LOGPEN* pLogPen) const
+       {
+               ATLASSERT(m_hPen != NULL);
+               return ::GetObject(m_hPen, sizeof(LOGPEN), pLogPen);
+       }
+
+       bool GetLogPen(LOGPEN& LogPen) const
+       {
+               ATLASSERT(m_hPen != NULL);
+               return (::GetObject(m_hPen, sizeof(LOGPEN), &LogPen) == sizeof(LOGPEN));
+       }
+
+#ifndef _WIN32_WCE
+       int GetExtLogPen(EXTLOGPEN* pLogPen) const
+       {
+               ATLASSERT(m_hPen != NULL);
+               return ::GetObject(m_hPen, sizeof(EXTLOGPEN), pLogPen);
+       }
+
+       bool GetExtLogPen(EXTLOGPEN& ExtLogPen) const
+       {
+               ATLASSERT(m_hPen != NULL);
+               return (::GetObject(m_hPen, sizeof(EXTLOGPEN), &ExtLogPen) == sizeof(EXTLOGPEN));
+       }
+#endif // !_WIN32_WCE
+};
+
+typedef CPenT<false>   CPenHandle;
+typedef CPenT<true>    CPen;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CBrush
+
+template <bool t_bManaged>
+class CBrushT
+{
+public:
+// Data members
+       HBRUSH m_hBrush;
+
+// Constructor/destructor/operators
+       CBrushT(HBRUSH hBrush = NULL) : m_hBrush(hBrush)
+       { }
+
+       ~CBrushT()
+       {
+               if(t_bManaged && m_hBrush != NULL)
+                       DeleteObject();
+       }
+
+       CBrushT<t_bManaged>& operator =(HBRUSH hBrush)
+       {
+               Attach(hBrush);
+               return *this;
+       }
+
+       void Attach(HBRUSH hBrush)
+       {
+               if(t_bManaged && m_hBrush != NULL && m_hBrush != hBrush)
+                       ::DeleteObject(m_hBrush);
+               m_hBrush = hBrush;
+       }
+
+       HBRUSH Detach()
+       {
+               HBRUSH hBrush = m_hBrush;
+               m_hBrush = NULL;
+               return hBrush;
+       }
+
+       operator HBRUSH() const { return m_hBrush; }
+
+       bool IsNull() const { return (m_hBrush == NULL); }
+
+// Create methods
+       HBRUSH CreateSolidBrush(COLORREF crColor)
+       {
+               ATLASSERT(m_hBrush == NULL);
+               m_hBrush = ::CreateSolidBrush(crColor);
+               return m_hBrush;
+       }
+
+#ifndef _WIN32_WCE
+       HBRUSH CreateHatchBrush(int nIndex, COLORREF crColor)
+       {
+               ATLASSERT(m_hBrush == NULL);
+               m_hBrush = ::CreateHatchBrush(nIndex, crColor);
+               return m_hBrush;
+       }
+#endif // !_WIN32_WCE
+
+#if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
+       HBRUSH CreateBrushIndirect(const LOGBRUSH* lpLogBrush)
+       {
+               ATLASSERT(m_hBrush == NULL);
+#ifndef _WIN32_WCE
+               m_hBrush = ::CreateBrushIndirect(lpLogBrush);
+#else // CE specific
+               m_hBrush = ATL::CreateBrushIndirect(lpLogBrush);
+#endif // _WIN32_WCE
+               return m_hBrush;
+       }
+#endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
+
+       HBRUSH CreatePatternBrush(HBITMAP hBitmap)
+       {
+               ATLASSERT(m_hBrush == NULL);
+               m_hBrush = ::CreatePatternBrush(hBitmap);
+               return m_hBrush;
+       }
+
+       HBRUSH CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage)
+       {
+               ATLASSERT(hPackedDIB != NULL);
+               const void* lpPackedDIB = GlobalLock(hPackedDIB);
+               ATLASSERT(lpPackedDIB != NULL);
+               m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage);
+               GlobalUnlock(hPackedDIB);
+               return m_hBrush;
+       }
+
+       HBRUSH CreateDIBPatternBrush(const void* lpPackedDIB, UINT nUsage)
+       {
+               ATLASSERT(m_hBrush == NULL);
+               m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage);
+               return m_hBrush;
+       }
+
+       HBRUSH CreateSysColorBrush(int nIndex)
+       {
+               ATLASSERT(m_hBrush == NULL);
+               m_hBrush = ::GetSysColorBrush(nIndex);
+               return m_hBrush;
+       }
+
+       BOOL DeleteObject()
+       {
+               ATLASSERT(m_hBrush != NULL);
+               BOOL bRet = ::DeleteObject(m_hBrush);
+               if(bRet)
+                       m_hBrush = NULL;
+               return bRet;
+       }
+
+// Attributes
+       int GetLogBrush(LOGBRUSH* pLogBrush) const
+       {
+               ATLASSERT(m_hBrush != NULL);
+               return ::GetObject(m_hBrush, sizeof(LOGBRUSH), pLogBrush);
+       }
+
+       bool GetLogBrush(LOGBRUSH& LogBrush) const
+       {
+               ATLASSERT(m_hBrush != NULL);
+               return (::GetObject(m_hBrush, sizeof(LOGBRUSH), &LogBrush) == sizeof(LOGBRUSH));
+       }
+};
+
+typedef CBrushT<false>   CBrushHandle;
+typedef CBrushT<true>    CBrush;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CFont
+
+class CLogFont : public LOGFONT
+{
+public:
+       CLogFont()
+       {
+               memset(this, 0, sizeof(LOGFONT));
+       }
+
+       CLogFont(const LOGFONT& lf)
+       {
+               Copy(&lf);
+       }
+
+       CLogFont(HFONT hFont)
+       {
+               ATLASSERT(::GetObjectType(hFont) == OBJ_FONT);
+               ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this);
+       }
+
+       HFONT CreateFontIndirect()
+       {
+               return ::CreateFontIndirect(this);
+       }
+
+       void SetBold()
+       {
+               lfWeight = FW_BOLD;
+       }
+
+       bool IsBold() const
+       {
+               return (lfWeight >= FW_BOLD);
+       }
+
+       void MakeBolder(int iScale = 1)
+       {
+               lfWeight += FW_BOLD * iScale;
+       }
+
+       void MakeLarger(int iScale)
+       {
+               if(lfHeight > 0)
+                       lfHeight += iScale;
+               else
+                       lfHeight -= iScale;
+       }
+
+       void SetHeight(LONG nPointSize, HDC hDC = NULL)
+       {
+               // For MM_TEXT mapping mode
+               lfHeight = -::MulDiv(nPointSize, ::GetDeviceCaps(hDC, LOGPIXELSY), 72);
+       }
+
+       LONG GetHeight(HDC hDC = NULL) const
+       {
+               // For MM_TEXT mapping mode
+               return ::MulDiv(-lfHeight, 72, ::GetDeviceCaps(hDC, LOGPIXELSY));
+       }
+
+       LONG GetDeciPointHeight(HDC hDC = NULL) const
+       {
+#ifndef _WIN32_WCE
+               POINT ptOrg = { 0, 0 };
+               ::DPtoLP(hDC, &ptOrg, 1);
+               POINT pt = { 0, 0 };
+               pt.y = abs(lfHeight) + ptOrg.y;
+               ::LPtoDP(hDC,&pt,1);
+               return ::MulDiv(pt.y, 720, ::GetDeviceCaps(hDC, LOGPIXELSY));   // 72 points/inch, 10 decipoints/point
+#else // CE specific
+               // DP and LP are always the same on CE
+               return ::MulDiv(abs(lfHeight), 720, ::GetDeviceCaps(hDC, LOGPIXELSY));   // 72 points/inch, 10 decipoints/point
+#endif // _WIN32_WCE
+       }
+
+       void SetHeightFromDeciPoint(LONG nDeciPtHeight, HDC hDC = NULL)
+       {
+#ifndef _WIN32_WCE
+               POINT pt = { 0, 0 };
+               pt.y = ::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), nDeciPtHeight, 720);   // 72 points/inch, 10 decipoints/point
+               ::DPtoLP(hDC, &pt, 1);
+               POINT ptOrg = { 0, 0 };
+               ::DPtoLP(hDC, &ptOrg, 1);
+               lfHeight = -abs(pt.y - ptOrg.y);
+#else // CE specific
+               // DP and LP are always the same on CE
+               lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), nDeciPtHeight, 720));   // 72 points/inch, 10 decipoints/point
+#endif // _WIN32_WCE
+       }
+
+#ifndef _WIN32_WCE
+       void SetCaptionFont()
+       {
+               NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
+               ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
+               Copy(&ncm.lfCaptionFont);
+       }
+
+       void SetMenuFont()
+       {
+               NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
+               ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
+               Copy(&ncm.lfMenuFont);
+       }
+
+       void SetStatusFont()
+       {
+               NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
+               ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
+               Copy(&ncm.lfStatusFont);
+       }
+
+       void SetMessageBoxFont()
+       {
+               NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
+               ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
+               Copy(&ncm.lfMessageFont);
+       }
+#endif // !_WIN32_WCE
+
+       void Copy(const LOGFONT* pLogFont)
+       {
+               ATLASSERT(pLogFont != NULL);
+               *(LOGFONT*)this = *pLogFont;
+       }
+
+       CLogFont& operator =(const CLogFont& src)
+       {
+               Copy(&src);
+               return *this;
+       }
+
+       CLogFont& operator =(const LOGFONT& src)
+       {
+               Copy(&src);
+               return *this;
+       }
+
+       CLogFont& operator =(HFONT hFont)
+       {
+               ATLASSERT(::GetObjectType(hFont) == OBJ_FONT);
+               ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this);
+               return *this;
+       }
+
+       bool operator ==(const LOGFONT& logfont) const
+       {
+               return(logfont.lfHeight == lfHeight &&
+                      logfont.lfWidth == lfWidth &&
+                      logfont.lfEscapement == lfEscapement &&
+                      logfont.lfOrientation == lfOrientation &&
+                      logfont.lfWeight == lfWeight &&
+                      logfont.lfItalic == lfItalic &&
+                      logfont.lfUnderline == lfUnderline &&
+                      logfont.lfStrikeOut == lfStrikeOut &&
+                      logfont.lfCharSet == lfCharSet &&
+                      logfont.lfOutPrecision == lfOutPrecision &&
+                      logfont.lfClipPrecision == lfClipPrecision &&
+                      logfont.lfQuality == lfQuality &&
+                      logfont.lfPitchAndFamily == lfPitchAndFamily &&
+                      lstrcmp(logfont.lfFaceName, lfFaceName) == 0);
+       }
+};
+
+
+template <bool t_bManaged>
+class CFontT
+{
+public:
+// Data members
+       HFONT m_hFont;
+
+// Constructor/destructor/operators
+       CFontT(HFONT hFont = NULL) : m_hFont(hFont)
+       { }
+
+       ~CFontT()
+       {
+               if(t_bManaged && m_hFont != NULL)
+                       DeleteObject();
+       }
+
+       CFontT<t_bManaged>& operator =(HFONT hFont)
+       {
+               Attach(hFont);
+               return *this;
+       }
+
+       void Attach(HFONT hFont)
+       {
+               if(t_bManaged && m_hFont != NULL && m_hFont != hFont)
+                       ::DeleteObject(m_hFont);
+               m_hFont = hFont;
+       }
+
+       HFONT Detach()
+       {
+               HFONT hFont = m_hFont;
+               m_hFont = NULL;
+               return hFont;
+       }
+
+       operator HFONT() const { return m_hFont; }
+
+       bool IsNull() const { return (m_hFont == NULL); }
+
+// Create methods
+       HFONT CreateFontIndirect(const LOGFONT* lpLogFont)
+       {
+               ATLASSERT(m_hFont == NULL);
+               m_hFont = ::CreateFontIndirect(lpLogFont);
+               return m_hFont;
+       }
+
+#if !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500)
+       HFONT CreateFontIndirectEx(CONST ENUMLOGFONTEXDV* penumlfex)
+       {
+               ATLASSERT(m_hFont == NULL);
+               m_hFont = ::CreateFontIndirectEx(penumlfex);
+               return m_hFont;
+       }
+#endif // !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500)
+
+#if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
+       HFONT CreateFont(int nHeight, int nWidth, int nEscapement,
+                       int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline,
+                       BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision,
+                       BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily,
+                       LPCTSTR lpszFacename)
+       {
+               ATLASSERT(m_hFont == NULL);
+#ifndef _WIN32_WCE
+               m_hFont = ::CreateFont(nHeight, nWidth, nEscapement,
+                       nOrientation, nWeight, bItalic, bUnderline, cStrikeOut,
+                       nCharSet, nOutPrecision, nClipPrecision, nQuality,
+                       nPitchAndFamily, lpszFacename);
+#else // CE specific
+               m_hFont = ATL::CreateFont(nHeight, nWidth, nEscapement,
+                       nOrientation, nWeight, bItalic, bUnderline, cStrikeOut,
+                       nCharSet, nOutPrecision, nClipPrecision, nQuality,
+                       nPitchAndFamily, lpszFacename);
+#endif // _WIN32_WCE
+               return m_hFont;
+       }
+#endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
+
+       HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, HDC hDC = NULL, bool bBold = false, bool bItalic = false)
+       {
+               LOGFONT logFont = { 0 };
+               logFont.lfCharSet = DEFAULT_CHARSET;
+               logFont.lfHeight = nPointSize;
+               SecureHelper::strncpy_x(logFont.lfFaceName, _countof(logFont.lfFaceName), lpszFaceName, _TRUNCATE);
+
+               if(bBold)
+                       logFont.lfWeight = FW_BOLD;
+               if(bItalic)
+                       logFont.lfItalic = (BYTE)TRUE;
+
+               return CreatePointFontIndirect(&logFont, hDC);
+       }
+
+       HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont, HDC hDC = NULL)
+       {
+               HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
+
+               // convert nPointSize to logical units based on hDC
+               LOGFONT logFont = *lpLogFont;
+#ifndef _WIN32_WCE
+               POINT pt = { 0, 0 };
+               pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720);   // 72 points/inch, 10 decipoints/point
+               ::DPtoLP(hDC1, &pt, 1);
+               POINT ptOrg = { 0, 0 };
+               ::DPtoLP(hDC1, &ptOrg, 1);
+               logFont.lfHeight = -abs(pt.y - ptOrg.y);
+#else // CE specific
+               // DP and LP are always the same on CE
+               logFont.lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720));   // 72 points/inch, 10 decipoints/point
+#endif // _WIN32_WCE
+
+               if(hDC == NULL)
+                       ::ReleaseDC(NULL, hDC1);
+
+               return CreateFontIndirect(&logFont);
+       }
+
+       BOOL DeleteObject()
+       {
+               ATLASSERT(m_hFont != NULL);
+               BOOL bRet = ::DeleteObject(m_hFont);
+               if(bRet)
+                       m_hFont = NULL;
+               return bRet;
+       }
+
+// Attributes
+       int GetLogFont(LOGFONT* pLogFont) const
+       {
+               ATLASSERT(m_hFont != NULL);
+               return ::GetObject(m_hFont, sizeof(LOGFONT), pLogFont);
+       }
+
+       bool GetLogFont(LOGFONT& LogFont) const
+       {
+               ATLASSERT(m_hFont != NULL);
+               return (::GetObject(m_hFont, sizeof(LOGFONT), &LogFont) == sizeof(LOGFONT));
+       }
+};
+
+typedef CFontT<false>   CFontHandle;
+typedef CFontT<true>    CFont;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CBitmap
+
+template <bool t_bManaged>
+class CBitmapT
+{
+public:
+// Data members
+       HBITMAP m_hBitmap;
+
+// Constructor/destructor/operators
+       CBitmapT(HBITMAP hBitmap = NULL) : m_hBitmap(hBitmap)
+       { }
+
+       ~CBitmapT()
+       {
+               if(t_bManaged && m_hBitmap != NULL)
+                       DeleteObject();
+       }
+
+       CBitmapT<t_bManaged>& operator =(HBITMAP hBitmap)
+       {
+               Attach(hBitmap);
+               return *this;
+       }
+
+       void Attach(HBITMAP hBitmap)
+       {
+               if(t_bManaged && m_hBitmap != NULL&& m_hBitmap != hBitmap)
+                       ::DeleteObject(m_hBitmap);
+               m_hBitmap = hBitmap;
+       }
+
+       HBITMAP Detach()
+       {
+               HBITMAP hBitmap = m_hBitmap;
+               m_hBitmap = NULL;
+               return hBitmap;
+       }
+
+       operator HBITMAP() const { return m_hBitmap; }
+
+       bool IsNull() const { return (m_hBitmap == NULL); }
+
+// Create and load methods
+       HBITMAP LoadBitmap(ATL::_U_STRINGorID bitmap)
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr);
+               return m_hBitmap;
+       }
+
+       HBITMAP LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap));
+               return m_hBitmap;
+       }
+
+#ifndef _WIN32_WCE
+       HBITMAP LoadMappedBitmap(UINT nIDBitmap, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0)
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::CreateMappedBitmap(ModuleHelper::GetResourceInstance(), nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize);
+               return m_hBitmap;
+       }
+#endif // !_WIN32_WCE
+
+       HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, const void* lpBits)
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::CreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpBits);
+               return m_hBitmap;
+       }
+
+#ifndef _WIN32_WCE
+       HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap)
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::CreateBitmapIndirect(lpBitmap);
+               return m_hBitmap;
+       }
+#endif // !_WIN32_WCE
+
+       HBITMAP CreateCompatibleBitmap(HDC hDC, int nWidth, int nHeight)
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight);
+               return m_hBitmap;
+       }
+
+#ifndef _WIN32_WCE
+       HBITMAP CreateDiscardableBitmap(HDC hDC, int nWidth, int nHeight)
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::CreateDiscardableBitmap(hDC, nWidth, nHeight);
+               return m_hBitmap;
+       }
+#endif // !_WIN32_WCE
+
+       BOOL DeleteObject()
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               BOOL bRet = ::DeleteObject(m_hBitmap);
+               if(bRet)
+                       m_hBitmap = NULL;
+               return bRet;
+       }
+
+// Attributes
+       int GetBitmap(BITMAP* pBitMap) const
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               return ::GetObject(m_hBitmap, sizeof(BITMAP), pBitMap);
+       }
+
+       bool GetBitmap(BITMAP& bm) const
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               return (::GetObject(m_hBitmap, sizeof(BITMAP), &bm) == sizeof(BITMAP));
+       }
+
+       bool GetSize(SIZE& size) const
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               BITMAP bm = { 0 };
+               if(!GetBitmap(&bm))
+                       return false;
+               size.cx = bm.bmWidth;
+               size.cy = bm.bmHeight;
+               return true;
+       }
+
+#ifndef _WIN32_WCE
+       DWORD GetBitmapBits(DWORD dwCount, LPVOID lpBits) const
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               return ::GetBitmapBits(m_hBitmap, dwCount, lpBits);
+       }
+#endif // !_WIN32_WCE
+
+#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410)
+       DWORD SetBitmapBits(DWORD dwCount, const void* lpBits)
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               return ::SetBitmapBits(m_hBitmap, dwCount, lpBits);
+       }
+#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410)
+
+#ifndef _WIN32_WCE
+       BOOL GetBitmapDimension(LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               return ::GetBitmapDimensionEx(m_hBitmap, lpSize);
+       }
+
+       BOOL SetBitmapDimension(int nWidth, int nHeight, LPSIZE lpSize = NULL)
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               return ::SetBitmapDimensionEx(m_hBitmap, nWidth, nHeight, lpSize);
+       }
+
+// DIB support
+       HBITMAP CreateDIBitmap(HDC hDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse)
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::CreateDIBitmap(hDC, lpbmih, dwInit, lpbInit, lpbmi, uColorUse);
+               return m_hBitmap;
+       }
+#endif // !_WIN32_WCE
+
+       HBITMAP CreateDIBSection(HDC hDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, VOID** ppvBits, HANDLE hSection, DWORD dwOffset)
+       {
+               ATLASSERT(m_hBitmap == NULL);
+               m_hBitmap = ::CreateDIBSection(hDC, lpbmi, uColorUse, ppvBits, hSection, dwOffset);
+               return m_hBitmap;
+       }
+
+#ifndef _WIN32_WCE
+       int GetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines,  LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               return ::GetDIBits(hDC, m_hBitmap, uStartScan, cScanLines,  lpvBits, lpbmi, uColorUse);
+       }
+
+       int SetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse)
+       {
+               ATLASSERT(m_hBitmap != NULL);
+               return ::SetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
+       }
+#endif // !_WIN32_WCE
+};
+
+typedef CBitmapT<false>   CBitmapHandle;
+typedef CBitmapT<true>    CBitmap;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPalette
+
+template <bool t_bManaged>
+class CPaletteT
+{
+public:
+// Data members
+       HPALETTE m_hPalette;
+
+// Constructor/destructor/operators
+       CPaletteT(HPALETTE hPalette = NULL) : m_hPalette(hPalette)
+       { }
+
+       ~CPaletteT()
+       {
+               if(t_bManaged && m_hPalette != NULL)
+                       DeleteObject();
+       }
+
+       CPaletteT<t_bManaged>& operator =(HPALETTE hPalette)
+       {
+               Attach(hPalette);
+               return *this;
+       }
+
+       void Attach(HPALETTE hPalette)
+       {
+               if(t_bManaged && m_hPalette != NULL && m_hPalette != hPalette)
+                       ::DeleteObject(m_hPalette);
+               m_hPalette = hPalette;
+       }
+
+       HPALETTE Detach()
+       {
+               HPALETTE hPalette = m_hPalette;
+               m_hPalette = NULL;
+               return hPalette;
+       }
+
+       operator HPALETTE() const { return m_hPalette; }
+
+       bool IsNull() const { return (m_hPalette == NULL); }
+
+// Create methods
+       HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette)
+       {
+               ATLASSERT(m_hPalette == NULL);
+               m_hPalette = ::CreatePalette(lpLogPalette);
+               return m_hPalette;
+       }
+
+#ifndef _WIN32_WCE
+       HPALETTE CreateHalftonePalette(HDC hDC)
+       {
+               ATLASSERT(m_hPalette == NULL);
+               ATLASSERT(hDC != NULL);
+               m_hPalette = ::CreateHalftonePalette(hDC);
+               return m_hPalette;
+       }
+#endif // !_WIN32_WCE
+
+       BOOL DeleteObject()
+       {
+               ATLASSERT(m_hPalette != NULL);
+               BOOL bRet = ::DeleteObject(m_hPalette);
+               if(bRet)
+                       m_hPalette = NULL;
+               return bRet;
+       }
+
+// Attributes
+       int GetEntryCount() const
+       {
+               ATLASSERT(m_hPalette != NULL);
+               WORD nEntries = 0;
+               ::GetObject(m_hPalette, sizeof(WORD), &nEntries);
+               return (int)nEntries;
+       }
+
+       UINT GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const
+       {
+               ATLASSERT(m_hPalette != NULL);
+               return ::GetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
+       }
+
+       UINT SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
+       {
+               ATLASSERT(m_hPalette != NULL);
+               return ::SetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
+       }
+
+// Operations
+#ifndef _WIN32_WCE
+       void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
+       {
+               ATLASSERT(m_hPalette != NULL);
+               ::AnimatePalette(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
+       }
+
+       BOOL ResizePalette(UINT nNumEntries)
+       {
+               ATLASSERT(m_hPalette != NULL);
+               return ::ResizePalette(m_hPalette, nNumEntries);
+       }
+#endif // !_WIN32_WCE
+
+       UINT GetNearestPaletteIndex(COLORREF crColor) const
+       {
+               ATLASSERT(m_hPalette != NULL);
+               return ::GetNearestPaletteIndex(m_hPalette, crColor);
+       }
+};
+
+typedef CPaletteT<false>   CPaletteHandle;
+typedef CPaletteT<true>    CPalette;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CRgn
+
+template <bool t_bManaged>
+class CRgnT
+{
+public:
+// Data members
+       HRGN m_hRgn;
+
+// Constructor/destructor/operators
+       CRgnT(HRGN hRgn = NULL) : m_hRgn(hRgn)
+       { }
+
+       ~CRgnT()
+       {
+               if(t_bManaged && m_hRgn != NULL)
+                       DeleteObject();
+       }
+
+       CRgnT<t_bManaged>& operator =(HRGN hRgn)
+       {
+               Attach(hRgn);
+               return *this;
+       }
+
+       void Attach(HRGN hRgn)
+       {
+               if(t_bManaged && m_hRgn != NULL && m_hRgn != hRgn)
+                       ::DeleteObject(m_hRgn);
+               m_hRgn = hRgn;
+       }
+
+       HRGN Detach()
+       {
+               HRGN hRgn = m_hRgn;
+               m_hRgn = NULL;
+               return hRgn;
+       }
+
+       operator HRGN() const { return m_hRgn; }
+
+       bool IsNull() const { return (m_hRgn == NULL); }
+
+// Create methods
+       HRGN CreateRectRgn(int x1, int y1, int x2, int y2)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               m_hRgn = ::CreateRectRgn(x1, y1, x2, y2);
+               return m_hRgn;
+       }
+
+       HRGN CreateRectRgnIndirect(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               m_hRgn = ::CreateRectRgnIndirect(lpRect);
+               return m_hRgn;
+       }
+
+#ifndef _WIN32_WCE
+       HRGN CreateEllipticRgn(int x1, int y1, int x2, int y2)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               m_hRgn = ::CreateEllipticRgn(x1, y1, x2, y2);
+               return m_hRgn;
+       }
+
+       HRGN CreateEllipticRgnIndirect(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               m_hRgn = ::CreateEllipticRgnIndirect(lpRect);
+               return m_hRgn;
+       }
+
+       HRGN CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               m_hRgn = ::CreatePolygonRgn(lpPoints, nCount, nMode);
+               return m_hRgn;
+       }
+
+       HRGN CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               m_hRgn = ::CreatePolyPolygonRgn(lpPoints, lpPolyCounts, nCount, nPolyFillMode);
+               return m_hRgn;
+       }
+
+       HRGN CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               m_hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, x3, y3);
+               return m_hRgn;
+       }
+
+       HRGN CreateFromPath(HDC hDC)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               ATLASSERT(hDC != NULL);
+               m_hRgn = ::PathToRegion(hDC);
+               return m_hRgn;
+       }
+
+       HRGN CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData)
+       {
+               ATLASSERT(m_hRgn == NULL);
+               m_hRgn = ::ExtCreateRegion(lpXForm, nCount, pRgnData);
+               return m_hRgn;
+       }
+#endif // !_WIN32_WCE
+
+       BOOL DeleteObject()
+       {
+               ATLASSERT(m_hRgn != NULL);
+               BOOL bRet = ::DeleteObject(m_hRgn);
+               if(bRet)
+                       m_hRgn = NULL;
+               return bRet;
+       }
+
+// Operations
+       void SetRectRgn(int x1, int y1, int x2, int y2)
+       {
+               ATLASSERT(m_hRgn != NULL);
+               ::SetRectRgn(m_hRgn, x1, y1, x2, y2);
+       }
+
+       void SetRectRgn(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hRgn != NULL);
+               ::SetRectRgn(m_hRgn, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
+       }
+
+       int CombineRgn(HRGN hRgnSrc1, HRGN hRgnSrc2, int nCombineMode)
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::CombineRgn(m_hRgn, hRgnSrc1, hRgnSrc2, nCombineMode);
+       }
+
+       int CombineRgn(HRGN hRgnSrc, int nCombineMode)
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::CombineRgn(m_hRgn, m_hRgn, hRgnSrc, nCombineMode);
+       }
+
+       int CopyRgn(HRGN hRgnSrc)
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::CombineRgn(m_hRgn, hRgnSrc, NULL, RGN_COPY);
+       }
+
+       BOOL EqualRgn(HRGN hRgn) const
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::EqualRgn(m_hRgn, hRgn);
+       }
+
+       int OffsetRgn(int x, int y)
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::OffsetRgn(m_hRgn, x, y);
+       }
+
+       int OffsetRgn(POINT point)
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::OffsetRgn(m_hRgn, point.x, point.y);
+       }
+
+       int GetRgnBox(LPRECT lpRect) const
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::GetRgnBox(m_hRgn, lpRect);
+       }
+
+       BOOL PtInRegion(int x, int y) const
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::PtInRegion(m_hRgn, x, y);
+       }
+
+       BOOL PtInRegion(POINT point) const
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::PtInRegion(m_hRgn, point.x, point.y);
+       }
+
+       BOOL RectInRegion(LPCRECT lpRect) const
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return ::RectInRegion(m_hRgn, lpRect);
+       }
+
+       int GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const
+       {
+               ATLASSERT(m_hRgn != NULL);
+               return (int)::GetRegionData(m_hRgn, nDataSize, lpRgnData);
+       }
+};
+
+typedef CRgnT<false>   CRgnHandle;
+typedef CRgnT<true>    CRgn;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDC - The device context class
+
+template <bool t_bManaged>
+class CDCT
+{
+public:
+// Data members
+       HDC m_hDC;
+
+// Constructor/destructor/operators
+       CDCT(HDC hDC = NULL) : m_hDC(hDC)
+       {
+       }
+
+       ~CDCT()
+       {
+               if(t_bManaged && m_hDC != NULL)
+                       ::DeleteDC(Detach());
+       }
+
+       CDCT<t_bManaged>& operator =(HDC hDC)
+       {
+               Attach(hDC);
+               return *this;
+       }
+
+       void Attach(HDC hDC)
+       {
+               if(t_bManaged && m_hDC != NULL && m_hDC != hDC)
+                       ::DeleteDC(m_hDC);
+               m_hDC = hDC;
+       }
+
+       HDC Detach()
+       {
+               HDC hDC = m_hDC;
+               m_hDC = NULL;
+               return hDC;
+       }
+
+       operator HDC() const { return m_hDC; }
+
+       bool IsNull() const { return (m_hDC == NULL); }
+
+// Operations
+#ifndef _WIN32_WCE
+       HWND WindowFromDC() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::WindowFromDC(m_hDC);
+       }
+#endif // !_WIN32_WCE
+
+       CPenHandle GetCurrentPen() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return CPenHandle((HPEN)::GetCurrentObject(m_hDC, OBJ_PEN));
+       }
+
+       CBrushHandle GetCurrentBrush() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return CBrushHandle((HBRUSH)::GetCurrentObject(m_hDC, OBJ_BRUSH));
+       }
+
+       CPaletteHandle GetCurrentPalette() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return CPaletteHandle((HPALETTE)::GetCurrentObject(m_hDC, OBJ_PAL));
+       }
+
+       CFontHandle GetCurrentFont() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return CFontHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT));
+       }
+
+       CBitmapHandle GetCurrentBitmap() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return CBitmapHandle((HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP));
+       }
+
+       HDC CreateDC(LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, const DEVMODE* lpInitData)
+       {
+               ATLASSERT(m_hDC == NULL);
+               m_hDC = ::CreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData);
+               return m_hDC;
+       }
+
+       HDC CreateCompatibleDC(HDC hDC = NULL)
+       {
+               ATLASSERT(m_hDC == NULL);
+               m_hDC = ::CreateCompatibleDC(hDC);
+               return m_hDC;
+       }
+
+       BOOL DeleteDC()
+       {
+               if(m_hDC == NULL)
+                       return FALSE;
+               BOOL bRet = ::DeleteDC(m_hDC);
+               if(bRet)
+                       m_hDC = NULL;
+               return bRet;
+       }
+
+// Device-Context Functions
+       int SaveDC()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SaveDC(m_hDC);
+       }
+
+       BOOL RestoreDC(int nSavedDC)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::RestoreDC(m_hDC, nSavedDC);
+       }
+
+       int GetDeviceCaps(int nIndex) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetDeviceCaps(m_hDC, nIndex);
+       }
+
+#ifndef _WIN32_WCE
+       UINT SetBoundsRect(LPCRECT lpRectBounds, UINT flags)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetBoundsRect(m_hDC, lpRectBounds, flags);
+       }
+
+       UINT GetBoundsRect(LPRECT lpRectBounds, UINT flags) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetBoundsRect(m_hDC, lpRectBounds, flags);
+       }
+
+       BOOL ResetDC(const DEVMODE* lpDevMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ResetDC(m_hDC, lpDevMode) != NULL;
+       }
+
+// Drawing-Tool Functions
+       BOOL GetBrushOrg(LPPOINT lpPoint) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetBrushOrgEx(m_hDC, lpPoint);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL SetBrushOrg(int x, int y, LPPOINT lpPoint = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetBrushOrgEx(m_hDC, x, y, lpPoint);
+       }
+
+       BOOL SetBrushOrg(POINT point, LPPOINT lpPointRet = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetBrushOrgEx(m_hDC, point.x, point.y, lpPointRet);
+       }
+
+#ifndef _WIN32_WCE
+       int EnumObjects(int nObjectType, int (CALLBACK* lpfn)(LPVOID, LPARAM), LPARAM lpData)
+       {
+               ATLASSERT(m_hDC != NULL);
+#ifdef STRICT
+               return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, lpData);
+#else
+               return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, (LPVOID)lpData);
+#endif
+       }
+#endif // !_WIN32_WCE
+
+// Type-safe selection helpers
+       HPEN SelectPen(HPEN hPen)
+       {
+               ATLASSERT(m_hDC != NULL);
+#ifndef _WIN32_WCE
+               ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN || ::GetObjectType(hPen) == OBJ_EXTPEN);
+#else // CE specific
+               ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN);
+#endif // _WIN32_WCE
+               return (HPEN)::SelectObject(m_hDC, hPen);
+       }
+
+       HBRUSH SelectBrush(HBRUSH hBrush)
+       {
+               ATLASSERT(m_hDC != NULL);
+               ATLASSERT(hBrush == NULL || ::GetObjectType(hBrush) == OBJ_BRUSH);
+               return (HBRUSH)::SelectObject(m_hDC, hBrush);
+       }
+
+       HFONT SelectFont(HFONT hFont)
+       {
+               ATLASSERT(m_hDC != NULL);
+               ATLASSERT(hFont == NULL || ::GetObjectType(hFont) == OBJ_FONT);
+               return (HFONT)::SelectObject(m_hDC, hFont);
+       }
+
+       HBITMAP SelectBitmap(HBITMAP hBitmap)
+       {
+               ATLASSERT(m_hDC != NULL);
+               ATLASSERT(hBitmap == NULL || ::GetObjectType(hBitmap) == OBJ_BITMAP);
+               return (HBITMAP)::SelectObject(m_hDC, hBitmap);
+       }
+
+       int SelectRgn(HRGN hRgn)       // special return for regions
+       {
+               ATLASSERT(m_hDC != NULL);
+               ATLASSERT(hRgn == NULL || ::GetObjectType(hRgn) == OBJ_REGION);
+               return PtrToInt(::SelectObject(m_hDC, hRgn));
+       }
+
+// Type-safe selection helpers for stock objects
+       HPEN SelectStockPen(int nPen)
+       {
+               ATLASSERT(m_hDC != NULL);
+#if (_WIN32_WINNT >= 0x0500)
+               ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN);
+#else
+               ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN);
+#endif // !(_WIN32_WINNT >= 0x0500)
+               return SelectPen((HPEN)::GetStockObject(nPen));
+       }
+
+       HBRUSH SelectStockBrush(int nBrush)
+       {
+#if (_WIN32_WINNT >= 0x0500)
+               ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH);
+#else
+               ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH);
+#endif // !(_WIN32_WINNT >= 0x0500)
+               return SelectBrush((HBRUSH)::GetStockObject(nBrush));
+       }
+
+       HFONT SelectStockFont(int nFont)
+       {
+#ifndef _WIN32_WCE
+               ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT);
+#else // CE specific
+               ATLASSERT(nFont == SYSTEM_FONT);
+#endif // _WIN32_WCE
+               return SelectFont((HFONT)::GetStockObject(nFont));
+       }
+
+       HPALETTE SelectStockPalette(int nPalette, BOOL bForceBackground)
+       {
+               ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported
+               return SelectPalette((HPALETTE)::GetStockObject(nPalette), bForceBackground);
+       }
+
+// Color and Color Palette Functions
+       COLORREF GetNearestColor(COLORREF crColor) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetNearestColor(m_hDC, crColor);
+       }
+
+       HPALETTE SelectPalette(HPALETTE hPalette, BOOL bForceBackground)
+       {
+               ATLASSERT(m_hDC != NULL);
+
+               return ::SelectPalette(m_hDC, hPalette, bForceBackground);
+       }
+
+       UINT RealizePalette()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::RealizePalette(m_hDC);
+       }
+
+#ifndef _WIN32_WCE
+       void UpdateColors()
+       {
+               ATLASSERT(m_hDC != NULL);
+               ::UpdateColors(m_hDC);
+       }
+#endif // !_WIN32_WCE
+
+// Drawing-Attribute Functions
+       COLORREF GetBkColor() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetBkColor(m_hDC);
+       }
+
+       int GetBkMode() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetBkMode(m_hDC);
+       }
+
+#ifndef _WIN32_WCE
+       int GetPolyFillMode() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetPolyFillMode(m_hDC);
+       }
+
+       int GetROP2() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetROP2(m_hDC);
+       }
+
+       int GetStretchBltMode() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetStretchBltMode(m_hDC);
+       }
+#endif // !_WIN32_WCE
+
+       COLORREF GetTextColor() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextColor(m_hDC);
+       }
+
+       COLORREF SetBkColor(COLORREF crColor)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetBkColor(m_hDC, crColor);
+       }
+
+       int SetBkMode(int nBkMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetBkMode(m_hDC, nBkMode);
+       }
+
+#ifndef _WIN32_WCE
+       int SetPolyFillMode(int nPolyFillMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetPolyFillMode(m_hDC, nPolyFillMode);
+       }
+#endif // !_WIN32_WCE
+
+       int SetROP2(int nDrawMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetROP2(m_hDC, nDrawMode);
+       }
+
+#ifndef _WIN32_WCE
+       int SetStretchBltMode(int nStretchMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetStretchBltMode(m_hDC, nStretchMode);
+       }
+#endif // !_WIN32_WCE
+
+       COLORREF SetTextColor(COLORREF crColor)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetTextColor(m_hDC, crColor);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetColorAdjustment(LPCOLORADJUSTMENT lpColorAdjust) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetColorAdjustment(m_hDC, lpColorAdjust);
+       }
+
+       BOOL SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetColorAdjustment(m_hDC, lpColorAdjust);
+       }
+
+// Mapping Functions
+       int GetMapMode() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetMapMode(m_hDC);
+       }
+
+       BOOL GetViewportOrg(LPPOINT lpPoint) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetViewportOrgEx(m_hDC, lpPoint);
+       }
+
+       int SetMapMode(int nMapMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetMapMode(m_hDC, nMapMode);
+       }
+#endif // !_WIN32_WCE
+
+       // Viewport Origin
+       BOOL SetViewportOrg(int x, int y, LPPOINT lpPoint = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetViewportOrgEx(m_hDC, x, y, lpPoint);
+       }
+
+       BOOL SetViewportOrg(POINT point, LPPOINT lpPointRet = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return SetViewportOrg(point.x, point.y, lpPointRet);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL OffsetViewportOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, lpPoint);
+       }
+
+       // Viewport Extent
+       BOOL GetViewportExt(LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetViewportExtEx(m_hDC, lpSize);
+       }
+
+       BOOL SetViewportExt(int x, int y, LPSIZE lpSize = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetViewportExtEx(m_hDC, x, y, lpSize);
+       }
+
+       BOOL SetViewportExt(SIZE size, LPSIZE lpSizeRet = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return SetViewportExt(size.cx, size.cy, lpSizeRet);
+       }
+
+       BOOL ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize);
+       }
+#endif // !_WIN32_WCE
+
+       // Window Origin
+#ifndef _WIN32_WCE
+       BOOL GetWindowOrg(LPPOINT lpPoint) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetWindowOrgEx(m_hDC, lpPoint);
+       }
+
+       BOOL SetWindowOrg(int x, int y, LPPOINT lpPoint = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetWindowOrgEx(m_hDC, x, y, lpPoint);
+       }
+
+       BOOL SetWindowOrg(POINT point, LPPOINT lpPointRet = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return SetWindowOrg(point.x, point.y, lpPointRet);
+       }
+
+       BOOL OffsetWindowOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::OffsetWindowOrgEx(m_hDC, nWidth, nHeight, lpPoint);
+       }
+
+       // Window extent
+       BOOL GetWindowExt(LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetWindowExtEx(m_hDC, lpSize);
+       }
+
+       BOOL SetWindowExt(int x, int y, LPSIZE lpSize = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetWindowExtEx(m_hDC, x, y, lpSize);
+       }
+
+       BOOL SetWindowExt(SIZE size, LPSIZE lpSizeRet = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return SetWindowExt(size.cx, size.cy, lpSizeRet);
+       }
+
+       BOOL ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ScaleWindowExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize);
+       }
+
+// Coordinate Functions
+       BOOL DPtoLP(LPPOINT lpPoints, int nCount = 1) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DPtoLP(m_hDC, lpPoints, nCount);
+       }
+
+       BOOL DPtoLP(LPRECT lpRect) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DPtoLP(m_hDC, (LPPOINT)lpRect, 2);
+       }
+
+       BOOL DPtoLP(LPSIZE lpSize) const
+       {
+               SIZE sizeWinExt = { 0, 0 };
+               if(!GetWindowExt(&sizeWinExt))
+                       return FALSE;
+               SIZE sizeVpExt = { 0, 0 };
+               if(!GetViewportExt(&sizeVpExt))
+                       return FALSE;
+               lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeWinExt.cx), abs(sizeVpExt.cx));
+               lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeWinExt.cy), abs(sizeVpExt.cy));
+               return TRUE;
+       }
+
+       BOOL LPtoDP(LPPOINT lpPoints, int nCount = 1) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::LPtoDP(m_hDC, lpPoints, nCount);
+       }
+
+       BOOL LPtoDP(LPRECT lpRect) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::LPtoDP(m_hDC, (LPPOINT)lpRect, 2);
+       }
+
+       BOOL LPtoDP(LPSIZE lpSize) const
+       {
+               SIZE sizeWinExt = { 0, 0 };
+               if(!GetWindowExt(&sizeWinExt))
+                       return FALSE;
+               SIZE sizeVpExt = { 0, 0 };
+               if(!GetViewportExt(&sizeVpExt))
+                       return FALSE;
+               lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx));
+               lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy));
+               return TRUE;
+       }
+
+// Special Coordinate Functions (useful for dealing with metafiles and OLE)
+       #define HIMETRIC_INCH   2540    // HIMETRIC units per inch
+
+       void DPtoHIMETRIC(LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               int nMapMode;
+               if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT)
+               {
+                       // when using a constrained map mode, map against physical inch
+                       ((CDCHandle*)this)->SetMapMode(MM_HIMETRIC);
+                       DPtoLP(lpSize);
+                       ((CDCHandle*)this)->SetMapMode(nMapMode);
+               }
+               else
+               {
+                       // map against logical inch for non-constrained mapping modes
+                       int cxPerInch = GetDeviceCaps(LOGPIXELSX);
+                       int cyPerInch = GetDeviceCaps(LOGPIXELSY);
+                       ATLASSERT(cxPerInch != 0 && cyPerInch != 0);
+                       lpSize->cx = ::MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch);
+                       lpSize->cy = ::MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch);
+               }
+       }
+
+       void HIMETRICtoDP(LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               int nMapMode;
+               if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT)
+               {
+                       // when using a constrained map mode, map against physical inch
+                       ((CDCHandle*)this)->SetMapMode(MM_HIMETRIC);
+                       LPtoDP(lpSize);
+                       ((CDCHandle*)this)->SetMapMode(nMapMode);
+               }
+               else
+               {
+                       // map against logical inch for non-constrained mapping modes
+                       int cxPerInch = GetDeviceCaps(LOGPIXELSX);
+                       int cyPerInch = GetDeviceCaps(LOGPIXELSY);
+                       ATLASSERT(cxPerInch != 0 && cyPerInch != 0);
+                       lpSize->cx = ::MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH);
+                       lpSize->cy = ::MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH);
+               }
+       }
+
+       void LPtoHIMETRIC(LPSIZE lpSize) const
+       {
+               LPtoDP(lpSize);
+               DPtoHIMETRIC(lpSize);
+       }
+
+       void HIMETRICtoLP(LPSIZE lpSize) const
+       {
+               HIMETRICtoDP(lpSize);
+               DPtoLP(lpSize);
+       }
+#endif // !_WIN32_WCE
+
+// Region Functions
+       BOOL FillRgn(HRGN hRgn, HBRUSH hBrush)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::FillRgn(m_hDC, hRgn, hBrush);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL FrameRgn(HRGN hRgn, HBRUSH hBrush, int nWidth, int nHeight)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::FrameRgn(m_hDC, hRgn, hBrush, nWidth, nHeight);
+       }
+
+       BOOL InvertRgn(HRGN hRgn)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::InvertRgn(m_hDC, hRgn);
+       }
+
+       BOOL PaintRgn(HRGN hRgn)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PaintRgn(m_hDC, hRgn);
+       }
+#endif // !_WIN32_WCE
+
+// Clipping Functions
+       int GetClipBox(LPRECT lpRect) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetClipBox(m_hDC, lpRect);
+       }
+
+       int GetClipRgn(CRgn& region) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               if(region.IsNull())
+                       region.CreateRectRgn(0, 0, 0, 0);
+
+               int nRet = ::GetClipRgn(m_hDC, region);
+               if(nRet != 1)
+                       region.DeleteObject();
+
+               return nRet;
+       }
+
+#ifndef _WIN32_WCE
+       BOOL PtVisible(int x, int y) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PtVisible(m_hDC, x, y);
+       }
+
+       BOOL PtVisible(POINT point) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PtVisible(m_hDC, point.x, point.y);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL RectVisible(LPCRECT lpRect) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::RectVisible(m_hDC, lpRect);
+       }
+
+       int SelectClipRgn(HRGN hRgn)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SelectClipRgn(m_hDC, (HRGN)hRgn);
+       }
+
+       int ExcludeClipRect(int x1, int y1, int x2, int y2)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ExcludeClipRect(m_hDC, x1, y1, x2, y2);
+       }
+
+       int ExcludeClipRect(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ExcludeClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
+       }
+
+#ifndef _WIN32_WCE
+       int ExcludeUpdateRgn(HWND hWnd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ExcludeUpdateRgn(m_hDC, hWnd);
+       }
+#endif // !_WIN32_WCE
+
+       int IntersectClipRect(int x1, int y1, int x2, int y2)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::IntersectClipRect(m_hDC, x1, y1, x2, y2);
+       }
+
+       int IntersectClipRect(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::IntersectClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
+       }
+
+#ifndef _WIN32_WCE
+       int OffsetClipRgn(int x, int y)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::OffsetClipRgn(m_hDC, x, y);
+       }
+
+       int OffsetClipRgn(SIZE size)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::OffsetClipRgn(m_hDC, size.cx, size.cy);
+       }
+
+       int SelectClipRgn(HRGN hRgn, int nMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ExtSelectClipRgn(m_hDC, hRgn, nMode);
+       }
+#endif // !_WIN32_WCE
+
+// Line-Output Functions
+#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+       BOOL GetCurrentPosition(LPPOINT lpPoint) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetCurrentPositionEx(m_hDC, lpPoint);
+       }
+
+       BOOL MoveTo(int x, int y, LPPOINT lpPoint = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::MoveToEx(m_hDC, x, y, lpPoint);
+       }
+
+       BOOL MoveTo(POINT point, LPPOINT lpPointRet = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return MoveTo(point.x, point.y, lpPointRet);
+       }
+
+       BOOL LineTo(int x, int y)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::LineTo(m_hDC, x, y);
+       }
+
+       BOOL LineTo(POINT point)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return LineTo(point.x, point.y);
+       }
+#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+
+#ifndef _WIN32_WCE
+       BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Arc(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+       }
+
+       BOOL Arc(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Arc(m_hDC, lpRect->left, lpRect->top,
+                       lpRect->right, lpRect->bottom, ptStart.x, ptStart.y,
+                       ptEnd.x, ptEnd.y);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL Polyline(LPPOINT lpPoints, int nCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Polyline(m_hDC, lpPoints, nCount);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::AngleArc(m_hDC, x, y, nRadius, fStartAngle, fSweepAngle);
+       }
+
+       BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ArcTo(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+       }
+
+       BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ArcTo(lpRect->left, lpRect->top, lpRect->right,
+               lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+       }
+
+       int GetArcDirection() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetArcDirection(m_hDC);
+       }
+
+       int SetArcDirection(int nArcDirection)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetArcDirection(m_hDC, nArcDirection);
+       }
+
+       BOOL PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PolyDraw(m_hDC, lpPoints, lpTypes, nCount);
+       }
+
+       BOOL PolylineTo(const POINT* lpPoints, int nCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PolylineTo(m_hDC, lpPoints, nCount);
+       }
+
+       BOOL PolyPolyline(const POINT* lpPoints,
+               const DWORD* lpPolyPoints, int nCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PolyPolyline(m_hDC, lpPoints, lpPolyPoints, nCount);
+       }
+
+       BOOL PolyBezier(const POINT* lpPoints, int nCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PolyBezier(m_hDC, lpPoints, nCount);
+       }
+
+       BOOL PolyBezierTo(const POINT* lpPoints, int nCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PolyBezierTo(m_hDC, lpPoints, nCount);
+       }
+#endif // !_WIN32_WCE
+
+// Simple Drawing Functions
+       BOOL FillRect(LPCRECT lpRect, HBRUSH hBrush)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::FillRect(m_hDC, lpRect, hBrush);
+       }
+
+       BOOL FillRect(LPCRECT lpRect, int nColorIndex)
+       {
+               ATLASSERT(m_hDC != NULL);
+#ifndef _WIN32_WCE
+               return ::FillRect(m_hDC, lpRect, (HBRUSH)LongToPtr(nColorIndex + 1));
+#else // CE specific
+               return ::FillRect(m_hDC, lpRect, ::GetSysColorBrush(nColorIndex));
+#endif // _WIN32_WCE
+       }
+
+#ifndef _WIN32_WCE
+       BOOL FrameRect(LPCRECT lpRect, HBRUSH hBrush)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::FrameRect(m_hDC, lpRect, hBrush);
+       }
+#endif // !_WIN32_WCE
+
+#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 420)
+       BOOL InvertRect(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::InvertRect(m_hDC, lpRect);
+       }
+#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420)
+
+       BOOL DrawIcon(int x, int y, HICON hIcon)
+       {
+               ATLASSERT(m_hDC != NULL);
+#ifndef _WIN32_WCE
+               return ::DrawIcon(m_hDC, x, y, hIcon);
+#else // CE specific
+               return ::DrawIconEx(m_hDC, x, y, hIcon, 0, 0, 0, NULL, DI_NORMAL);
+#endif // _WIN32_WCE
+       }
+
+       BOOL DrawIcon(POINT point, HICON hIcon)
+       {
+               ATLASSERT(m_hDC != NULL);
+#ifndef _WIN32_WCE
+               return ::DrawIcon(m_hDC, point.x, point.y, hIcon);
+#else // CE specific
+               return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, 0, 0, 0, NULL, DI_NORMAL);
+#endif // _WIN32_WCE
+       }
+
+       BOOL DrawIconEx(int x, int y, HICON hIcon, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawIconEx(m_hDC, x, y, hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
+       }
+
+       BOOL DrawIconEx(POINT point, HICON hIcon, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL DrawState(POINT pt, SIZE size, HBITMAP hBitmap, UINT nFlags, HBRUSH hBrush = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hBitmap, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_BITMAP);
+       }
+
+       BOOL DrawState(POINT pt, SIZE size, HICON hIcon, UINT nFlags, HBRUSH hBrush = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hIcon, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_ICON);
+       }
+
+       BOOL DrawState(POINT pt, SIZE size, LPCTSTR lpszText, UINT nFlags, BOOL bPrefixText = TRUE, int nTextLen = 0, HBRUSH hBrush = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)lpszText, (WPARAM)nTextLen, pt.x, pt.y, size.cx, size.cy, nFlags | (bPrefixText ? DST_PREFIXTEXT : DST_TEXT));
+       }
+
+       BOOL DrawState(POINT pt, SIZE size, DRAWSTATEPROC lpDrawProc, LPARAM lData, UINT nFlags, HBRUSH hBrush = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawState(m_hDC, hBrush, lpDrawProc, lData, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_COMPLEX);
+       }
+#endif // !_WIN32_WCE
+
+// Ellipse and Polygon Functions
+#ifndef _WIN32_WCE
+       BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Chord(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+       }
+
+       BOOL Chord(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Chord(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+       }
+#endif // !_WIN32_WCE
+
+       void DrawFocusRect(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hDC != NULL);
+               ::DrawFocusRect(m_hDC, lpRect);
+       }
+
+       BOOL Ellipse(int x1, int y1, int x2, int y2)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Ellipse(m_hDC, x1, y1, x2, y2);
+       }
+
+       BOOL Ellipse(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Ellipse(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Pie(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+       }
+
+       BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Pie(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL Polygon(LPPOINT lpPoints, int nCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Polygon(m_hDC, lpPoints, nCount);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PolyPolygon(m_hDC, lpPoints, lpPolyCounts, nCount);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL Rectangle(int x1, int y1, int x2, int y2)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Rectangle(m_hDC, x1, y1, x2, y2);
+       }
+
+       BOOL Rectangle(LPCRECT lpRect)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Rectangle(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
+       }
+
+       BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::RoundRect(m_hDC, x1, y1, x2, y2, x3, y3);
+       }
+
+       BOOL RoundRect(LPCRECT lpRect, POINT point)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::RoundRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, point.x, point.y);
+       }
+
+// Bitmap Functions
+       BOOL PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PatBlt(m_hDC, x, y, nWidth, nHeight, dwRop);
+       }
+
+       BOOL BitBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC,
+               int xSrc, int ySrc, DWORD dwRop)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::BitBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, dwRop);
+       }
+
+       BOOL StretchBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::StretchBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop);
+       }
+
+       COLORREF GetPixel(int x, int y) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetPixel(m_hDC, x, y);
+       }
+
+       COLORREF GetPixel(POINT point) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetPixel(m_hDC, point.x, point.y);
+       }
+
+       COLORREF SetPixel(int x, int y, COLORREF crColor)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetPixel(m_hDC, x, y, crColor);
+       }
+
+       COLORREF SetPixel(POINT point, COLORREF crColor)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetPixel(m_hDC, point.x, point.y, crColor);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL FloodFill(int x, int y, COLORREF crColor)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::FloodFill(m_hDC, x, y, crColor);
+       }
+
+       BOOL ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ExtFloodFill(m_hDC, x, y, crColor, nFillType);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL MaskBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, HBITMAP hMaskBitmap, int xMask, int yMask, DWORD dwRop)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::MaskBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, hMaskBitmap, xMask, yMask, dwRop);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL PlgBlt(LPPOINT lpPoint, HDC hSrcDC, int xSrc, int ySrc, int nWidth, int nHeight, HBITMAP hMaskBitmap, int xMask, int yMask)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PlgBlt(m_hDC, lpPoint, hSrcDC, xSrc, ySrc, nWidth, nHeight, hMaskBitmap, xMask, yMask);
+       }
+
+       BOOL SetPixelV(int x, int y, COLORREF crColor)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetPixelV(m_hDC, x, y, crColor);
+       }
+
+       BOOL SetPixelV(POINT point, COLORREF crColor)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetPixelV(m_hDC, point.x, point.y, crColor);
+       }
+#endif // !_WIN32_WCE
+
+#if !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE)
+#ifndef _WIN32_WCE
+       BOOL TransparentBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::TransparentBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent);
+       }
+#else // CE specific
+       BOOL TransparentImage(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::TransparentImage(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent);
+       }
+#endif // _WIN32_WCE
+
+#if (!defined(_WIN32_WCE) || (_WIN32_WCE >= 420))
+       BOOL GradientFill(const PTRIVERTEX pVertices, DWORD nVertices, void* pMeshElements, DWORD nMeshElements, DWORD dwMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GradientFill(m_hDC, pVertices, nVertices, pMeshElements, nMeshElements, dwMode);
+       }
+#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420)
+
+#if !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500)
+       BOOL AlphaBlend(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, BLENDFUNCTION bf)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::AlphaBlend(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, bf);
+       }
+#endif // !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500)
+#endif //  !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE)
+
+// Extra bitmap functions
+       // Helper function for painting a disabled toolbar or menu bitmap
+       // This function can take either an HBITMAP (for SS) or a DC with 
+       //           the bitmap already painted (for cmdbar)
+       BOOL DitherBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, HBITMAP hBitmap, int xSrc, int ySrc,
+                       HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE),
+                       HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT),
+                       HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW))
+       {
+               ATLASSERT(m_hDC != NULL || hBitmap != NULL);
+               ATLASSERT(nWidth > 0 && nHeight > 0);
+               
+               // Create a generic DC for all BitBlts
+               CDCHandle dc = (hSrcDC != NULL) ? hSrcDC : ::CreateCompatibleDC(m_hDC);
+               ATLASSERT(dc.m_hDC != NULL);
+               if(dc.m_hDC == NULL)
+                       return FALSE;
+               
+               // Create a DC for the monochrome DIB section
+               CDC dcBW = ::CreateCompatibleDC(m_hDC);
+               ATLASSERT(dcBW.m_hDC != NULL);
+               if(dcBW.m_hDC == NULL)
+               {
+                       if(hSrcDC == NULL)
+                               dc.DeleteDC();
+                       return FALSE;
+               }
+
+               // Create the monochrome DIB section with a black and white palette
+               struct RGBBWBITMAPINFO
+               {
+                       BITMAPINFOHEADER bmiHeader; 
+                       RGBQUAD bmiColors[2]; 
+               };
+
+               RGBBWBITMAPINFO rgbBWBitmapInfo = 
+               {
+                       { sizeof(BITMAPINFOHEADER), nWidth, nHeight, 1, 1, BI_RGB, 0, 0, 0, 0, 0 },
+                       { { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 } }
+               };
+
+               VOID* pbitsBW;
+               CBitmap bmpBW = ::CreateDIBSection(dcBW, (LPBITMAPINFO)&rgbBWBitmapInfo, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
+               ATLASSERT(bmpBW.m_hBitmap != NULL);
+               if(bmpBW.m_hBitmap == NULL)
+               {
+                       if(hSrcDC == NULL)
+                               dc.DeleteDC();
+                       return FALSE;
+               }
+               
+               // Attach the monochrome DIB section and the bitmap to the DCs
+               HBITMAP hbmOldBW = dcBW.SelectBitmap(bmpBW);
+               HBITMAP hbmOldDC = NULL;
+               if(hBitmap != NULL)
+                       hbmOldDC = dc.SelectBitmap(hBitmap);
+
+               // Block: Dark gray removal: we want (128, 128, 128) pixels to become black and not white
+               {
+                       CDC dcTemp1 = ::CreateCompatibleDC(m_hDC);
+                       CDC dcTemp2 = ::CreateCompatibleDC(m_hDC);
+                       CBitmap bmpTemp1;
+                       bmpTemp1.CreateCompatibleBitmap(dc, nWidth, nHeight);
+                       CBitmap bmpTemp2;
+                       bmpTemp2.CreateBitmap(nWidth, nHeight, 1, 1, NULL);
+                       HBITMAP hOldBmp1 = dcTemp1.SelectBitmap(bmpTemp1);
+                       HBITMAP hOldBmp2 = dcTemp2.SelectBitmap(bmpTemp2);
+                       // Let's copy our image, it will be altered
+                       dcTemp1.BitBlt(0, 0, nWidth, nHeight, dc, xSrc, ySrc, SRCCOPY);
+
+                       // All dark gray pixels will become white, the others black
+                       dcTemp1.SetBkColor(RGB(128, 128, 128));
+                       dcTemp2.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY);
+                       // Do an XOR to set to black these white pixels
+                       dcTemp1.BitBlt(0, 0, nWidth, nHeight, dcTemp2, 0, 0, SRCINVERT);
+
+                       // BitBlt the bitmap into the monochrome DIB section
+                       // The DIB section will do a true monochrome conversion
+                       // The magenta background being closer to white will become white
+                       dcBW.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY);
+
+                       // Cleanup
+                       dcTemp1.SelectBitmap(hOldBmp1);
+                       dcTemp2.SelectBitmap(hOldBmp2);
+               }
+               
+               // Paint the destination rectangle using hBrushBackground
+               if(hBrushBackground != NULL)
+               {
+                       RECT rc = { x, y, x + nWidth, y + nHeight };
+                       FillRect(&rc, hBrushBackground);
+               }
+
+               // BitBlt the black bits in the monochrome bitmap into hBrush3DEffect color in the destination DC
+               // The magic ROP comes from the Charles Petzold's book
+               HBRUSH hOldBrush = SelectBrush(hBrush3DEffect);
+               BitBlt(x + 1, y + 1, nWidth, nHeight, dcBW, 0, 0, 0xB8074A);
+
+               // BitBlt the black bits in the monochrome bitmap into hBrushDisabledImage color in the destination DC
+               SelectBrush(hBrushDisabledImage);
+               BitBlt(x, y, nWidth, nHeight, dcBW, 0, 0, 0xB8074A);
+
+               SelectBrush(hOldBrush);
+               dcBW.SelectBitmap(hbmOldBW);
+               dc.SelectBitmap(hbmOldDC);
+
+               if(hSrcDC == NULL)
+                       dc.DeleteDC();
+
+               return TRUE;
+       }
+
+// Text Functions
+#ifndef _WIN32_WCE
+       BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount = -1)
+       {
+               ATLASSERT(m_hDC != NULL);
+               if(nCount == -1)
+                       nCount = lstrlen(lpszString);
+               return ::TextOut(m_hDC, x, y, lpszString, nCount);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL ExtTextOut(int x, int y, UINT nOptions, LPCRECT lpRect, LPCTSTR lpszString, UINT nCount = -1, LPINT lpDxWidths = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               if(nCount == -1)
+                       nCount = lstrlen(lpszString);
+               return ::ExtTextOut(m_hDC, x, y, nOptions, lpRect, lpszString, nCount, lpDxWidths);
+       }
+
+#ifndef _WIN32_WCE
+       SIZE TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL, int nTabOrigin = 0)
+       {
+               ATLASSERT(m_hDC != NULL);
+               if(nCount == -1)
+                       nCount = lstrlen(lpszString);
+               LONG lRes = ::TabbedTextOut(m_hDC, x, y, lpszString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin);
+               SIZE size = { GET_X_LPARAM(lRes), GET_Y_LPARAM(lRes) };
+               return size;
+       }
+#endif // !_WIN32_WCE
+
+       int DrawText(LPCTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat)
+       {
+               ATLASSERT(m_hDC != NULL);
+#ifndef _WIN32_WCE
+               ATLASSERT((uFormat & DT_MODIFYSTRING) == 0);
+#endif // !_WIN32_WCE
+               return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat);
+       }
+
+       int DrawText(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat);
+       }
+
+#ifndef _WIN32_WCE
+       int DrawTextEx(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat, LPDRAWTEXTPARAMS lpDTParams = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawTextEx(m_hDC, lpstrText, cchText, lpRect, uFormat, lpDTParams);
+       }
+#endif // !_WIN32_WCE
+
+#if (_WIN32_WINNT >= 0x0501)
+       int DrawShadowText(LPCWSTR lpstrText, int cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset)
+       {
+               ATLASSERT(m_hDC != NULL);
+               // This function is present only if comctl32.dll version 6 is loaded;
+               // we use LoadLibrary/GetProcAddress to allow apps compiled with
+               // _WIN32_WINNT >= 0x0501 to run on older Windows/CommCtrl
+               int nRet = 0;
+               HMODULE hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
+               ATLASSERT(hCommCtrlDLL != NULL);
+               if(hCommCtrlDLL != NULL)
+               {
+                       typedef int (WINAPI *PFN_DrawShadowText)(HDC hDC, LPCWSTR lpstrText, UINT cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset);
+                       PFN_DrawShadowText pfnDrawShadowText = (PFN_DrawShadowText)::GetProcAddress(hCommCtrlDLL, "DrawShadowText");
+                       ATLASSERT(pfnDrawShadowText != NULL);   // this function requires CommCtrl6
+                       if(pfnDrawShadowText != NULL)
+                               nRet = pfnDrawShadowText(m_hDC, lpstrText, cchText, lpRect, dwFlags, clrText, clrShadow, xOffset, yOffset);
+                       ::FreeLibrary(hCommCtrlDLL);
+               }
+               return nRet;
+       }
+#endif // (_WIN32_WINNT >= 0x0501)
+
+       BOOL GetTextExtent(LPCTSTR lpszString, int nCount, LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               if(nCount == -1)
+                       nCount = lstrlen(lpszString);
+               return ::GetTextExtentPoint32(m_hDC, lpszString, nCount, lpSize);
+       }
+
+       BOOL GetTextExtentExPoint(LPCTSTR lpszString, int cchString, LPSIZE lpSize, int nMaxExtent, LPINT lpnFit = NULL, LPINT alpDx = NULL)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextExtentExPoint(m_hDC, lpszString, cchString, nMaxExtent, lpnFit, alpDx, lpSize);
+       }
+
+#ifndef _WIN32_WCE
+       DWORD GetTabbedTextExtent(LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               if(nCount == -1)
+                       nCount = lstrlen(lpszString);
+               return ::GetTabbedTextExtent(m_hDC, lpszString, nCount, nTabPositions, lpnTabStopPositions);
+       }
+
+       BOOL GrayString(HBRUSH hBrush, BOOL (CALLBACK* lpfnOutput)(HDC, LPARAM, int), LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GrayString(m_hDC, hBrush, (GRAYSTRINGPROC)lpfnOutput, lpData, nCount, x, y, nWidth, nHeight);
+       }
+#endif // !_WIN32_WCE
+
+#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+       UINT GetTextAlign() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextAlign(m_hDC);
+       }
+
+       UINT SetTextAlign(UINT nFlags)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetTextAlign(m_hDC, nFlags);
+       }
+#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+
+       int GetTextFace(LPTSTR lpszFacename, int nCount) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextFace(m_hDC, nCount, lpszFacename);
+       }
+
+       int GetTextFaceLen() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextFace(m_hDC, 0, NULL);
+       }
+
+#ifndef _ATL_NO_COM
+#ifdef _OLEAUTO_H_
+       BOOL GetTextFace(BSTR& bstrFace) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(m_hDC != NULL);
+               ATLASSERT(bstrFace == NULL);
+
+               int nLen = GetTextFaceLen();
+               if(nLen == 0)
+                       return FALSE;
+
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpszText = buff.Allocate(nLen);
+               if(lpszText == NULL)
+                       return FALSE;
+
+               if(!GetTextFace(lpszText, nLen))
+                       return FALSE;
+
+               bstrFace = ::SysAllocString(T2OLE(lpszText));
+               return (bstrFace != NULL) ? TRUE : FALSE;
+       }
+#endif
+#endif // !_ATL_NO_COM
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       int GetTextFace(_CSTRING_NS::CString& strFace) const
+       {
+               ATLASSERT(m_hDC != NULL);
+
+               int nLen = GetTextFaceLen();
+               if(nLen == 0)
+                       return 0;
+
+               LPTSTR lpstr = strFace.GetBufferSetLength(nLen);
+               if(lpstr == NULL)
+                       return 0;
+               int nRet = GetTextFace(lpstr, nLen);
+               strFace.ReleaseBuffer();
+               return nRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextMetrics(m_hDC, lpMetrics);
+       }
+
+#ifndef _WIN32_WCE
+       int SetTextJustification(int nBreakExtra, int nBreakCount)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount);
+       }
+
+       int GetTextCharacterExtra() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextCharacterExtra(m_hDC);
+       }
+
+       int SetTextCharacterExtra(int nCharExtra)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetTextCharacterExtra(m_hDC, nCharExtra);
+       }
+#endif // !_WIN32_WCE
+
+// Advanced Drawing
+       BOOL DrawEdge(LPRECT lpRect, UINT nEdge, UINT nFlags)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawEdge(m_hDC, lpRect, nEdge, nFlags);
+       }
+
+       BOOL DrawFrameControl(LPRECT lpRect, UINT nType, UINT nState)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawFrameControl(m_hDC, lpRect, nType, nState);
+       }
+
+// Scrolling Functions
+       BOOL ScrollDC(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ScrollDC(m_hDC, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate);
+       }
+
+// Font Functions
+#ifndef _WIN32_WCE
+       BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetCharWidth(m_hDC, nFirstChar, nLastChar, lpBuffer);
+       }
+
+       // GetCharWidth32 is not supported under Win9x
+       BOOL GetCharWidth32(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetCharWidth32(m_hDC, nFirstChar, nLastChar, lpBuffer);
+       }
+
+       DWORD SetMapperFlags(DWORD dwFlag)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetMapperFlags(m_hDC, dwFlag);
+       }
+
+       BOOL GetAspectRatioFilter(LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetAspectRatioFilterEx(m_hDC, lpSize);
+       }
+
+       BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABC lpabc) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetCharABCWidths(m_hDC, nFirstChar, nLastChar, lpabc);
+       }
+
+       DWORD GetFontData(DWORD dwTable, DWORD dwOffset, LPVOID lpData, DWORD cbData) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetFontData(m_hDC, dwTable, dwOffset, lpData, cbData);
+       }
+
+       int GetKerningPairs(int nPairs, LPKERNINGPAIR lpkrnpair) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetKerningPairs(m_hDC, nPairs, lpkrnpair);
+       }
+
+       UINT GetOutlineTextMetrics(UINT cbData, LPOUTLINETEXTMETRIC lpotm) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetOutlineTextMetrics(m_hDC, cbData, lpotm);
+       }
+
+       DWORD GetGlyphOutline(UINT nChar, UINT nFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2* lpmat2) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetGlyphOutline(m_hDC, nChar, nFormat, lpgm, cbBuffer, lpBuffer, lpmat2);
+       }
+
+       BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABCFLOAT lpABCF) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetCharABCWidthsFloat(m_hDC, nFirstChar, nLastChar, lpABCF);
+       }
+
+       BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, float* lpFloatBuffer) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetCharWidthFloat(m_hDC, nFirstChar, nLastChar, lpFloatBuffer);
+       }
+#endif // !_WIN32_WCE
+
+// Printer/Device Escape Functions
+#ifndef _WIN32_WCE
+       int Escape(int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::Escape(m_hDC, nEscape, nCount, lpszInData, lpOutData);
+       }
+#endif // !_WIN32_WCE
+
+       int Escape(int nEscape, int nInputSize, LPCSTR lpszInputData,
+               int nOutputSize, LPSTR lpszOutputData)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ExtEscape(m_hDC, nEscape, nInputSize, lpszInputData, nOutputSize, lpszOutputData);
+       }
+
+#ifndef _WIN32_WCE
+       int DrawEscape(int nEscape, int nInputSize, LPCSTR lpszInputData)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DrawEscape(m_hDC, nEscape, nInputSize, lpszInputData);
+       }
+#endif // !_WIN32_WCE
+
+       // Escape helpers
+#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc))
+       int StartDoc(LPCTSTR lpszDocName)  // old Win3.0 version
+       {
+               DOCINFO di = { 0 };
+               di.cbSize = sizeof(DOCINFO);
+               di.lpszDocName = lpszDocName;
+               return StartDoc(&di);
+       }
+
+       int StartDoc(LPDOCINFO lpDocInfo)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::StartDoc(m_hDC, lpDocInfo);
+       }
+
+       int StartPage()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::StartPage(m_hDC);
+       }
+
+       int EndPage()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::EndPage(m_hDC);
+       }
+
+       int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int))
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetAbortProc(m_hDC, (ABORTPROC)lpfn);
+       }
+
+       int AbortDoc()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::AbortDoc(m_hDC);
+       }
+
+       int EndDoc()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::EndDoc(m_hDC);
+       }
+#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc))
+
+// MetaFile Functions
+#ifndef _WIN32_WCE
+       BOOL PlayMetaFile(HMETAFILE hMF)
+       {
+               ATLASSERT(m_hDC != NULL);
+               if(::GetDeviceCaps(m_hDC, TECHNOLOGY) == DT_METAFILE)
+               {
+                       // playing metafile in metafile, just use core windows API
+                       return ::PlayMetaFile(m_hDC, hMF);
+               }
+
+               // for special playback, lParam == pDC
+               return ::EnumMetaFile(m_hDC, hMF, EnumMetaFileProc, (LPARAM)this);
+       }
+
+       BOOL PlayMetaFile(HENHMETAFILE hEnhMetaFile, LPCRECT lpBounds)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::PlayEnhMetaFile(m_hDC, hEnhMetaFile, lpBounds);
+       }
+
+       BOOL AddMetaFileComment(UINT nDataSize, const BYTE* pCommentData) // can be used for enhanced metafiles only
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GdiComment(m_hDC, nDataSize, pCommentData);
+       }
+
+       // Special handling for metafile playback
+       static int CALLBACK EnumMetaFileProc(HDC hDC, HANDLETABLE* pHandleTable, METARECORD* pMetaRec, int nHandles, LPARAM lParam)
+       {
+               CDCHandle* pDC = (CDCHandle*)lParam;
+
+               switch (pMetaRec->rdFunction)
+               {
+               case META_SETMAPMODE:
+                       pDC->SetMapMode((int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_SETWINDOWEXT:
+                       pDC->SetWindowExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_SETWINDOWORG:
+                       pDC->SetWindowOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_SETVIEWPORTEXT:
+                       pDC->SetViewportExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_SETVIEWPORTORG:
+                       pDC->SetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_SCALEWINDOWEXT:
+                       pDC->ScaleWindowExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2], 
+                               (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_SCALEVIEWPORTEXT:
+                       pDC->ScaleViewportExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],
+                               (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_OFFSETVIEWPORTORG:
+                       pDC->OffsetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_SAVEDC:
+                       pDC->SaveDC();
+                       break;
+               case META_RESTOREDC:
+                       pDC->RestoreDC((int)(short)pMetaRec->rdParm[0]);
+                       break;
+               case META_SETBKCOLOR:
+                       pDC->SetBkColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
+                       break;
+               case META_SETTEXTCOLOR:
+                       pDC->SetTextColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
+                       break;
+
+               // need to watch out for SelectObject(HFONT), for custom font mapping
+               case META_SELECTOBJECT:
+                       {
+                               HGDIOBJ hObject = pHandleTable->objectHandle[pMetaRec->rdParm[0]];
+                               UINT nObjType = ::GetObjectType(hObject);
+                               if(nObjType == 0)
+                               {
+                                       // object type is unknown, determine if it is a font
+                                       HFONT hStockFont = (HFONT)::GetStockObject(SYSTEM_FONT);
+                                       HFONT hFontOld = (HFONT)::SelectObject(pDC->m_hDC, hStockFont);
+                                       HGDIOBJ hObjOld = ::SelectObject(pDC->m_hDC, hObject);
+                                       if(hObjOld == hStockFont)
+                                       {
+                                               // got the stock object back, so must be selecting a font
+                                               pDC->SelectFont((HFONT)hObject);
+                                               break;  // don't play the default record
+                                       }
+                                       else
+                                       {
+                                               // didn't get the stock object back, so restore everything
+                                               ::SelectObject(pDC->m_hDC, hFontOld);
+                                               ::SelectObject(pDC->m_hDC, hObjOld);
+                                       }
+                                       // and fall through to PlayMetaFileRecord...
+                               }
+                               else if(nObjType == OBJ_FONT)
+                               {
+                                       // play back as CDCHandle::SelectFont(HFONT)
+                                       pDC->SelectFont((HFONT)hObject);
+                                       break;  // don't play the default record
+                               }
+                       }
+                       // fall through...
+
+               default:
+                       ::PlayMetaFileRecord(hDC, pHandleTable, pMetaRec, nHandles);
+                       break;
+               }
+
+               return 1;
+       }
+#endif // !_WIN32_WCE
+
+// Path Functions
+#ifndef _WIN32_WCE
+       BOOL AbortPath()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::AbortPath(m_hDC);
+       }
+
+       BOOL BeginPath()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::BeginPath(m_hDC);
+       }
+
+       BOOL CloseFigure()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::CloseFigure(m_hDC);
+       }
+
+       BOOL EndPath()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::EndPath(m_hDC);
+       }
+
+       BOOL FillPath()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::FillPath(m_hDC);
+       }
+
+       BOOL FlattenPath()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::FlattenPath(m_hDC);
+       }
+
+       BOOL StrokeAndFillPath()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::StrokeAndFillPath(m_hDC);
+       }
+
+       BOOL StrokePath()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::StrokePath(m_hDC);
+       }
+
+       BOOL WidenPath()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::WidenPath(m_hDC);
+       }
+
+       BOOL GetMiterLimit(PFLOAT pfMiterLimit) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetMiterLimit(m_hDC, pfMiterLimit);
+       }
+
+       BOOL SetMiterLimit(float fMiterLimit)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetMiterLimit(m_hDC, fMiterLimit, NULL);
+       }
+
+       int GetPath(LPPOINT lpPoints, LPBYTE lpTypes, int nCount) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetPath(m_hDC, lpPoints, lpTypes, nCount);
+       }
+
+       BOOL SelectClipPath(int nMode)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SelectClipPath(m_hDC, nMode);
+       }
+#endif // !_WIN32_WCE
+
+// Misc Helper Functions
+       static CBrushHandle PASCAL GetHalftoneBrush()
+       {
+               HBRUSH halftoneBrush = NULL;
+               WORD grayPattern[8];
+               for(int i = 0; i < 8; i++)
+                       grayPattern[i] = (WORD)(0x5555 << (i & 1));
+               HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern);
+               if(grayBitmap != NULL)
+               {
+                       halftoneBrush = ::CreatePatternBrush(grayBitmap);
+                       DeleteObject(grayBitmap);
+               }
+               return CBrushHandle(halftoneBrush);
+       }
+
+       void DrawDragRect(LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, HBRUSH hBrush = NULL, HBRUSH hBrushLast = NULL)
+       {
+               // first, determine the update region and select it
+               CRgn rgnOutside;
+               rgnOutside.CreateRectRgnIndirect(lpRect);
+               RECT rect = *lpRect;
+               ::InflateRect(&rect, -size.cx, -size.cy);
+               ::IntersectRect(&rect, &rect, lpRect);
+               CRgn rgnInside;
+               rgnInside.CreateRectRgnIndirect(&rect);
+               CRgn rgnNew;
+               rgnNew.CreateRectRgn(0, 0, 0, 0);
+               rgnNew.CombineRgn(rgnOutside, rgnInside, RGN_XOR);
+
+               HBRUSH hBrushOld = NULL;
+               CBrush brushHalftone;
+               if(hBrush == NULL)
+                       brushHalftone = hBrush = CDCHandle::GetHalftoneBrush();
+               if(hBrushLast == NULL)
+                       hBrushLast = hBrush;
+
+               CRgn rgnLast;
+               CRgn rgnUpdate;
+               if(lpRectLast != NULL)
+               {
+                       // find difference between new region and old region
+                       rgnLast.CreateRectRgn(0, 0, 0, 0);
+                       rgnOutside.SetRectRgn(lpRectLast->left, lpRectLast->top, lpRectLast->right, lpRectLast->bottom);
+                       rect = *lpRectLast;
+                       ::InflateRect(&rect, -sizeLast.cx, -sizeLast.cy);
+                       ::IntersectRect(&rect, &rect, lpRectLast);
+                       rgnInside.SetRectRgn(rect.left, rect.top, rect.right, rect.bottom);
+                       rgnLast.CombineRgn(rgnOutside, rgnInside, RGN_XOR);
+
+                       // only diff them if brushes are the same
+                       if(hBrush == hBrushLast)
+                       {
+                               rgnUpdate.CreateRectRgn(0, 0, 0, 0);
+                               rgnUpdate.CombineRgn(rgnLast, rgnNew, RGN_XOR);
+                       }
+               }
+               if(hBrush != hBrushLast && lpRectLast != NULL)
+               {
+                       // brushes are different -- erase old region first
+                       SelectClipRgn(rgnLast);
+                       GetClipBox(&rect);
+                       hBrushOld = SelectBrush(hBrushLast);
+                       PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
+                       SelectBrush(hBrushOld);
+                       hBrushOld = NULL;
+               }
+
+               // draw into the update/new region
+               SelectClipRgn(rgnUpdate.IsNull() ? rgnNew : rgnUpdate);
+               GetClipBox(&rect);
+               hBrushOld = SelectBrush(hBrush);
+               PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
+
+               // cleanup DC
+               if(hBrushOld != NULL)
+                       SelectBrush(hBrushOld);
+               SelectClipRgn(NULL);
+       }
+
+       void FillSolidRect(LPCRECT lpRect, COLORREF clr)
+       {
+               ATLASSERT(m_hDC != NULL);
+
+               COLORREF clrOld = ::SetBkColor(m_hDC, clr);
+               ATLASSERT(clrOld != CLR_INVALID);
+               if(clrOld != CLR_INVALID)
+               {
+                       ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
+                       ::SetBkColor(m_hDC, clrOld);
+               }
+       }
+
+       void FillSolidRect(int x, int y, int cx, int cy, COLORREF clr)
+       {
+               ATLASSERT(m_hDC != NULL);
+
+               RECT rect = { x, y, x + cx, y + cy };
+               FillSolidRect(&rect, clr);
+       }
+
+       void Draw3dRect(LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight)
+       {
+               Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left,
+                       lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
+       }
+
+       void Draw3dRect(int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight)
+       {
+               FillSolidRect(x, y, cx - 1, 1, clrTopLeft);
+               FillSolidRect(x, y, 1, cy - 1, clrTopLeft);
+               FillSolidRect(x + cx, y, -1, cy, clrBottomRight);
+               FillSolidRect(x, y + cy, cx, -1, clrBottomRight);
+       }
+
+// DIB support
+#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410)
+       int SetDIBitsToDevice(int x, int y, DWORD dwWidth, DWORD dwHeight, int xSrc, int ySrc, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetDIBitsToDevice(m_hDC, x, y, dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
+       }
+#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410)
+
+#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+       int StretchDIBits(int x, int y, int nWidth, int nHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse, DWORD dwRop)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::StretchDIBits(m_hDC, x, y, nWidth, nHeight, xSrc, ySrc, nSrcWidth, nSrcHeight, lpvBits, lpbmi, uColorUse, dwRop);
+       }
+
+       UINT GetDIBColorTable(UINT uStartIndex, UINT cEntries, RGBQUAD* pColors) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors);
+       }
+
+       UINT SetDIBColorTable(UINT uStartIndex, UINT cEntries, CONST RGBQUAD* pColors)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors);
+       }
+#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+
+// OpenGL support
+#if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE)
+       int ChoosePixelFormat(CONST PIXELFORMATDESCRIPTOR* ppfd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ChoosePixelFormat(m_hDC, ppfd);
+       }
+
+       int DescribePixelFormat(int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::DescribePixelFormat(m_hDC, iPixelFormat, nBytes, ppfd);
+       }
+
+       int GetPixelFormat() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetPixelFormat(m_hDC);
+       }
+
+       BOOL SetPixelFormat(int iPixelFormat, CONST PIXELFORMATDESCRIPTOR* ppfd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetPixelFormat(m_hDC, iPixelFormat, ppfd);
+       }
+
+       BOOL SwapBuffers()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SwapBuffers(m_hDC);
+       }
+
+       HGLRC wglCreateContext()
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglCreateContext(m_hDC);
+       }
+
+       HGLRC wglCreateLayerContext(int iLayerPlane)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglCreateLayerContext(m_hDC, iLayerPlane);
+       }
+
+       BOOL wglMakeCurrent(HGLRC hglrc)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglMakeCurrent(m_hDC, hglrc);
+       }
+
+       BOOL wglUseFontBitmaps(DWORD dwFirst, DWORD dwCount, DWORD listBase)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglUseFontBitmaps(m_hDC, dwFirst, dwCount, listBase);
+       }
+
+       BOOL wglUseFontOutlines(DWORD dwFirst, DWORD dwCount, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglUseFontOutlines(m_hDC, dwFirst, dwCount, listBase, deviation, extrusion, format, lpgmf);
+       }
+
+       BOOL wglDescribeLayerPlane(int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglDescribeLayerPlane(m_hDC, iPixelFormat, iLayerPlane, nBytes, plpd);
+       }
+
+       int wglSetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, CONST COLORREF* pclr)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglSetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr);
+       }
+
+       int wglGetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, COLORREF* pclr)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglGetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr);
+       }
+
+       BOOL wglRealizeLayerPalette(int iLayerPlane, BOOL bRealize)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglRealizeLayerPalette(m_hDC, iLayerPlane, bRealize);
+       }
+
+       BOOL wglSwapLayerBuffers(UINT uPlanes)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::wglSwapLayerBuffers(m_hDC, uPlanes);
+       }
+#endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE)
+
+// New for Windows 2000 only
+#if (_WIN32_WINNT >= 0x0500)
+       COLORREF GetDCPenColor() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetDCPenColor(m_hDC);
+       }
+
+       COLORREF SetDCPenColor(COLORREF clr)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetDCPenColor(m_hDC, clr);
+       }
+
+       COLORREF GetDCBrushColor() const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetDCBrushColor(m_hDC);
+       }
+
+       COLORREF SetDCBrushColor(COLORREF clr)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::SetDCBrushColor(m_hDC, clr);
+       }
+
+#ifndef _WIN32_WCE
+       DWORD GetFontUnicodeRanges(LPGLYPHSET lpgs) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetFontUnicodeRanges(m_hDC, lpgs);
+       }
+#endif // !_WIN32_WCE
+
+       DWORD GetGlyphIndices(LPCTSTR lpstr, int cch, LPWORD pgi, DWORD dwFlags) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetGlyphIndices(m_hDC, lpstr, cch, pgi, dwFlags);
+       }
+
+       BOOL GetTextExtentPointI(LPWORD pgiIn, int cgi, LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextExtentPointI(m_hDC, pgiIn, cgi, lpSize);
+       }
+
+       BOOL GetTextExtentExPointI(LPWORD pgiIn, int cgi, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetTextExtentExPointI(m_hDC, pgiIn, cgi, nMaxExtent, lpnFit, alpDx, lpSize);
+       }
+
+       BOOL GetCharWidthI(UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetCharWidthI(m_hDC, giFirst, cgi, pgi, lpBuffer);
+       }
+
+       BOOL GetCharABCWidthsI(UINT giFirst, UINT cgi, LPWORD pgi, LPABC lpabc) const
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::GetCharABCWidthsI(m_hDC, giFirst, cgi, pgi, lpabc);
+       }
+#endif // (_WIN32_WINNT >= 0x0500)
+
+// New for Windows 2000 and Windows 98
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+       BOOL ColorCorrectPalette(HPALETTE hPalette, DWORD dwFirstEntry, DWORD dwNumOfEntries)
+       {
+               ATLASSERT(m_hDC != NULL);
+               return ::ColorCorrectPalette(m_hDC, hPalette, dwFirstEntry, dwNumOfEntries);
+       }
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+};
+
+typedef CDCT<false>   CDCHandle;
+typedef CDCT<true>    CDC;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDC Helpers
+
+class CPaintDC : public CDC
+{
+public:
+// Data members
+       HWND m_hWnd;
+       PAINTSTRUCT m_ps;
+
+// Constructor/destructor
+       CPaintDC(HWND hWnd)
+       {
+               ATLASSERT(::IsWindow(hWnd));
+               m_hWnd = hWnd;
+               m_hDC = ::BeginPaint(hWnd, &m_ps);
+       }
+
+       ~CPaintDC()
+       {
+               ATLASSERT(m_hDC != NULL);
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::EndPaint(m_hWnd, &m_ps);
+               Detach();
+       }
+};
+
+class CClientDC : public CDC
+{
+public:
+// Data members
+       HWND m_hWnd;
+
+// Constructor/destructor
+       CClientDC(HWND hWnd)
+       {
+               ATLASSERT(hWnd == NULL || ::IsWindow(hWnd));
+               m_hWnd = hWnd;
+               m_hDC = ::GetDC(hWnd);
+       }
+
+       ~CClientDC()
+       {
+               ATLASSERT(m_hDC != NULL);
+               ::ReleaseDC(m_hWnd, Detach());
+       }
+};
+
+class CWindowDC : public CDC
+{
+public:
+// Data members
+       HWND m_hWnd;
+
+// Constructor/destructor
+       CWindowDC(HWND hWnd)
+       {
+               ATLASSERT(hWnd == NULL || ::IsWindow(hWnd));
+               m_hWnd = hWnd;
+               m_hDC = ::GetWindowDC(hWnd);
+       }
+
+       ~CWindowDC()
+       {
+               ATLASSERT(m_hDC != NULL);
+               ::ReleaseDC(m_hWnd, Detach());
+       }
+};
+
+class CMemoryDC : public CDC
+{
+public:
+// Data members
+       HDC m_hDCOriginal;
+       RECT m_rcPaint;
+       CBitmap m_bmp;
+       HBITMAP m_hBmpOld;
+
+// Constructor/destructor
+       CMemoryDC(HDC hDC, RECT& rcPaint) : m_hDCOriginal(hDC), m_hBmpOld(NULL)
+       {
+               m_rcPaint = rcPaint;
+               CreateCompatibleDC(m_hDCOriginal);
+               ATLASSERT(m_hDC != NULL);
+               m_bmp.CreateCompatibleBitmap(m_hDCOriginal, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top);
+               ATLASSERT(m_bmp.m_hBitmap != NULL);
+               m_hBmpOld = SelectBitmap(m_bmp);
+               SetViewportOrg(-m_rcPaint.left, -m_rcPaint.top);
+       }
+
+       ~CMemoryDC()
+       {
+               ::BitBlt(m_hDCOriginal, m_rcPaint.left, m_rcPaint.top, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top, m_hDC, m_rcPaint.left, m_rcPaint.top, SRCCOPY);
+               SelectBitmap(m_hBmpOld);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Enhanced metafile support
+
+#ifndef _WIN32_WCE
+
+class CEnhMetaFileInfo
+{
+public:
+// Data members
+       HENHMETAFILE m_hEMF;
+       BYTE* m_pBits;
+       TCHAR* m_pDesc;
+       ENHMETAHEADER m_header;
+       PIXELFORMATDESCRIPTOR m_pfd;
+
+// Constructor/destructor
+       CEnhMetaFileInfo(HENHMETAFILE hEMF) : m_pBits(NULL), m_pDesc(NULL), m_hEMF(hEMF)
+       { }
+
+       ~CEnhMetaFileInfo()
+       {
+               delete [] m_pBits;
+               delete [] m_pDesc;
+       }
+
+// Operations
+       BYTE* GetEnhMetaFileBits()
+       {
+               ATLASSERT(m_hEMF != NULL);
+               UINT nBytes = ::GetEnhMetaFileBits(m_hEMF, 0, NULL);
+               delete [] m_pBits;
+               m_pBits = NULL;
+               ATLTRY(m_pBits = new BYTE[nBytes]);
+               if (m_pBits != NULL)
+                       ::GetEnhMetaFileBits(m_hEMF, nBytes, m_pBits);
+               return m_pBits;
+       }
+
+       LPTSTR GetEnhMetaFileDescription()
+       {
+               ATLASSERT(m_hEMF != NULL);
+               UINT nLen = ::GetEnhMetaFileDescription(m_hEMF, 0, NULL);
+               delete [] m_pDesc;
+               m_pDesc = NULL;
+               ATLTRY(m_pDesc = new TCHAR[nLen]);
+               if (m_pDesc != NULL)
+                       nLen = ::GetEnhMetaFileDescription(m_hEMF, nLen, m_pDesc);
+               return m_pDesc;
+       }
+
+       ENHMETAHEADER* GetEnhMetaFileHeader()
+       {
+               ATLASSERT(m_hEMF != NULL);
+               memset(&m_header, 0, sizeof(m_header));
+               m_header.iType = EMR_HEADER;
+               m_header.nSize = sizeof(ENHMETAHEADER);
+               UINT n = ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), &m_header);
+               return (n != 0) ? &m_header : NULL;
+       }
+
+       PIXELFORMATDESCRIPTOR* GetEnhMetaFilePixelFormat()
+       {
+               ATLASSERT(m_hEMF != NULL);
+               memset(&m_pfd, 0, sizeof(m_pfd));
+               UINT n = ::GetEnhMetaFilePixelFormat(m_hEMF, sizeof(m_pfd), &m_pfd);
+               return (n != 0) ? &m_pfd : NULL;
+       }
+};
+
+
+template <bool t_bManaged>
+class CEnhMetaFileT
+{
+public:
+// Data members
+       HENHMETAFILE m_hEMF;
+
+// Constructor/destructor
+       CEnhMetaFileT(HENHMETAFILE hEMF = NULL) : m_hEMF(hEMF)
+       {
+       }
+
+       ~CEnhMetaFileT()
+       {
+               if(t_bManaged && m_hEMF != NULL)
+                       DeleteObject();
+       }
+
+// Operations
+       CEnhMetaFileT<t_bManaged>& operator =(HENHMETAFILE hEMF)
+       {
+               Attach(hEMF);
+               return *this;
+       }
+
+       void Attach(HENHMETAFILE hEMF)
+       {
+               if(t_bManaged && m_hEMF != NULL && m_hEMF != hEMF)
+                       DeleteObject();
+               m_hEMF = hEMF;
+       }
+
+       HENHMETAFILE Detach()
+       {
+               HENHMETAFILE hEMF = m_hEMF;
+               m_hEMF = NULL;
+               return hEMF;
+       }
+
+       operator HENHMETAFILE() const { return m_hEMF; }
+
+       bool IsNull() const { return (m_hEMF == NULL); }
+
+       BOOL DeleteObject()
+       {
+               ATLASSERT(m_hEMF != NULL);
+               BOOL bRet = ::DeleteEnhMetaFile(m_hEMF);
+               m_hEMF = NULL;
+               return bRet;
+       }
+
+       UINT GetEnhMetaFileBits(UINT cbBuffer, LPBYTE lpbBuffer) const
+       {
+               ATLASSERT(m_hEMF != NULL);
+               return ::GetEnhMetaFileBits(m_hEMF, cbBuffer, lpbBuffer);
+       }
+
+       UINT GetEnhMetaFileDescription(UINT cchBuffer, LPTSTR lpszDescription) const
+       {
+               ATLASSERT(m_hEMF != NULL);
+               return ::GetEnhMetaFileDescription(m_hEMF, cchBuffer, lpszDescription);
+       }
+
+       UINT GetEnhMetaFileHeader(LPENHMETAHEADER lpemh) const
+       {
+               ATLASSERT(m_hEMF != NULL);
+               lpemh->iType = EMR_HEADER;
+               lpemh->nSize = sizeof(ENHMETAHEADER);
+               return ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), lpemh);
+       }
+
+       UINT GetEnhMetaFilePaletteEntries(UINT cEntries, LPPALETTEENTRY lppe) const
+       {
+               ATLASSERT(m_hEMF != NULL);
+               return ::GetEnhMetaFilePaletteEntries(m_hEMF, cEntries, lppe);
+       }
+
+       UINT GetEnhMetaFilePixelFormat(DWORD cbBuffer, PIXELFORMATDESCRIPTOR* ppfd) const
+       {
+               ATLASSERT(m_hEMF != NULL);
+               return ::GetEnhMetaFilePixelFormat(m_hEMF, cbBuffer, ppfd);
+       }
+};
+
+typedef CEnhMetaFileT<false>   CEnhMetaFileHandle;
+typedef CEnhMetaFileT<true>    CEnhMetaFile;
+
+
+class CEnhMetaFileDC : public CDC
+{
+public:
+// Constructor/destructor
+       CEnhMetaFileDC()
+       {
+       }
+
+       CEnhMetaFileDC(HDC hdc, LPCRECT lpRect)
+       {
+               Create(hdc, NULL, lpRect, NULL);
+               ATLASSERT(m_hDC != NULL);
+       }
+
+       CEnhMetaFileDC(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription)
+       {
+               Create(hdcRef, lpFilename, lpRect, lpDescription);
+               ATLASSERT(m_hDC != NULL);
+       }
+
+       ~CEnhMetaFileDC()
+       {
+               HENHMETAFILE hEMF = Close();
+               if (hEMF != NULL)
+                       ::DeleteEnhMetaFile(hEMF);
+       }
+
+// Operations
+       void Create(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription)
+       {
+               ATLASSERT(m_hDC == NULL);
+               m_hDC = ::CreateEnhMetaFile(hdcRef, lpFilename, lpRect, lpDescription);
+       }
+
+       HENHMETAFILE Close()
+       {
+               HENHMETAFILE hEMF = NULL;
+               if (m_hDC != NULL)
+               {
+                       hEMF = ::CloseEnhMetaFile(m_hDC);
+                       m_hDC = NULL;
+               }
+               return hEMF;
+       }
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// WinCE compatible clipboard CF_DIB format support functions
+
+#ifndef _WTL_NO_DIB16
+
+#define DIBINFO16_BITFIELDS { 31744, 992, 31 }
+
+// DIBINFO16 - To avoid color table problems in WinCE we only create this type of Dib
+struct DIBINFO16 // a BITMAPINFO with 2 additional color bitfields
+{
+    BITMAPINFOHEADER    bmiHeader;
+    RGBQUAD             bmiColors[3];
+
+       DIBINFO16(SIZE size) 
+       {
+               BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), size.cx, size.cy, 
+                                         1, 16, BI_BITFIELDS, 2 * size.cx * size.cy , 0, 0, 3 };
+               DWORD dw[3] = DIBINFO16_BITFIELDS ;
+
+               bmiHeader = bmih;
+               memcpy(bmiColors, dw, 3 * sizeof(DWORD));
+       }
+};
+
+
+// AtlxxxDibxxx minimal packed DIB implementation and helpers to copy and paste CF_DIB
+inline bool AtlIsDib16(LPBITMAPINFOHEADER pbmih)
+{
+       return (pbmih->biBitCount == 16) && (pbmih->biCompression == BI_BITFIELDS);
+}
+
+inline int AtlGetDibColorTableSize(LPBITMAPINFOHEADER pbmih)
+{
+       switch (pbmih->biBitCount) 
+       {
+               case  2:
+               case  4:
+               case  8:
+                       return pbmih->biClrUsed ? pbmih->biClrUsed : 1 << pbmih->biBitCount;
+               case 24:
+                       break;
+               case 16:
+               case 32:
+                       return pbmih->biCompression == BI_BITFIELDS ? 3 : 0;
+               default:
+                       ATLASSERT(FALSE);   // should never come here
+       }
+
+       return 0;
+}
+
+inline int AtlGetDibNumColors(LPBITMAPINFOHEADER pbmih)
+{
+       switch (pbmih->biBitCount) 
+       {
+               case  2:
+               case  4:
+               case  8: 
+                       if (pbmih->biClrUsed)
+                               return pbmih->biClrUsed;
+                       else
+                               break;
+               case 16: 
+                       if (pbmih->biCompression == BI_BITFIELDS )
+                               return 1 << 15;
+                       else
+                               break;
+               case 24:
+                       break;
+               case 32: 
+                       if (pbmih->biCompression == BI_BITFIELDS )
+                               return 1 << 24;
+                       else
+                               break;
+               default:
+                       ATLASSERT(FALSE);
+       }
+
+       return 1 << pbmih->biBitCount;
+}
+
+inline HBITMAP AtlGetDibBitmap(LPBITMAPINFO pbmi)
+{
+       HBITMAP hbm = NULL;
+       CDC dc(NULL);
+       void * pBits = NULL;
+
+       LPBYTE pDibBits = (LPBYTE)pbmi + sizeof(BITMAPINFOHEADER) + AtlGetDibColorTableSize(&pbmi->bmiHeader) * sizeof(RGBQUAD);
+       if (hbm = CreateDIBSection(dc, pbmi, DIB_RGB_COLORS, &pBits, NULL, NULL)) 
+               memcpy(pBits, pDibBits, pbmi->bmiHeader.biSizeImage);
+
+       return hbm;
+}
+       
+inline HBITMAP AtlCopyBitmap(HBITMAP hbm , SIZE sizeDst, bool bAsBitmap = false)
+{
+       CDC hdcSrc = CreateCompatibleDC(NULL);
+       CDC hdcDst = CreateCompatibleDC(NULL);
+
+       CBitmapHandle hbmOld = NULL, hbmOld2 = NULL, bmSrc = hbm;
+
+       CBitmap bmNew = NULL;
+
+       SIZE sizeSrc = { 0 };
+       bmSrc.GetSize(sizeSrc);
+
+       hbmOld = hdcSrc.SelectBitmap(bmSrc);
+
+       if (bAsBitmap)
+       {
+               bmNew.CreateCompatibleBitmap(hdcSrc, sizeDst.cx, sizeDst.cy);
+       }
+       else
+       {
+               DIBINFO16 dib16(sizeDst);
+               LPVOID pBits = NULL;
+               bmNew = CreateDIBSection(hdcDst, (const BITMAPINFO*)&dib16, DIB_RGB_COLORS, &pBits, NULL, NULL);
+       }
+       
+       ATLASSERT(!bmNew.IsNull());
+
+       hbmOld2 = hdcDst.SelectBitmap(bmNew);
+       BOOL bOK = FALSE;
+
+       if ((sizeDst.cx == sizeSrc.cx) && (sizeDst.cy == sizeSrc.cy))
+               bOK = hdcDst.BitBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, SRCCOPY);
+       else
+               bOK = hdcDst.StretchBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, sizeSrc.cx, sizeSrc.cy, SRCCOPY);
+
+       hdcSrc.SelectBitmap(hbmOld);
+       hdcDst.SelectBitmap(hbmOld2);
+
+       if (bOK == FALSE)
+               bmNew.DeleteObject();
+
+       return bmNew.Detach();
+}
+
+inline HLOCAL AtlCreatePackedDib16(HBITMAP hbm, SIZE size)
+{
+       DIBSECTION ds = { 0 };
+       LPBYTE pDib = NULL;
+       bool bCopied = false;
+
+       bool bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds);
+       if ((bOK == FALSE) || (ds.dsBm.bmBits == NULL) || (AtlIsDib16(&ds.dsBmih) == FALSE) || 
+           (ds.dsBmih.biWidth != size.cx ) || (ds.dsBmih.biHeight != size.cy ))
+       {
+               if ((hbm = AtlCopyBitmap(hbm, size)) != NULL)
+               {
+                       bCopied = true;
+                       bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds);
+               }
+               else
+               {
+                       bOK = FALSE;
+               }
+       }
+
+       if((bOK == TRUE) && (AtlIsDib16(&ds.dsBmih) == TRUE) && (ds.dsBm.bmBits != NULL))
+       {
+               pDib = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, sizeof(DIBINFO16) + ds.dsBmih.biSizeImage);
+               if (pDib != NULL)
+               {
+                       memcpy(pDib , &ds.dsBmih, sizeof(DIBINFO16));
+                       memcpy(pDib + sizeof(DIBINFO16), ds.dsBm.bmBits, ds.dsBmih.biSizeImage);
+               }
+       }
+
+       if (bCopied == true)
+               DeleteObject(hbm);
+
+       return (HLOCAL)pDib;
+}
+
+inline bool AtlSetClipboardDib16(HBITMAP hbm, SIZE size, HWND hWnd)
+{
+       ATLASSERT(::IsWindow(hWnd));
+       BOOL bOK = OpenClipboard(hWnd);
+       if (bOK == TRUE)
+       {
+               if ((bOK = EmptyClipboard()) == TRUE)
+               {
+                       HLOCAL hDib = AtlCreatePackedDib16(hbm, size);
+                       if (hDib != NULL)
+                       {
+                               bOK = SetClipboardData(CF_DIB, hDib) != NULL;
+                               if (bOK == FALSE)  
+                                       LocalFree(hDib);
+                       }
+                       else
+                       {
+                               bOK = FALSE;
+                       }
+               }
+               CloseClipboard();
+       }
+
+       return bOK == TRUE;
+}
+
+inline HBITMAP AtlGetClipboardDib(HWND hWnd)
+{
+       ATLASSERT(::IsWindow(hWnd) == TRUE);
+       HBITMAP hbm = NULL;
+       if  (OpenClipboard(hWnd) == TRUE)
+       {
+               LPBITMAPINFO pbmi = (LPBITMAPINFO)GetClipboardData(CF_DIB);
+               if (pbmi != NULL)
+                       hbm = AtlGetDibBitmap(pbmi);
+               CloseClipboard();
+       }
+
+       return hbm;
+}
+
+#endif // _WTL_NO_DIB16
+
+}; // namespace WTL
+
+#endif // __ATLGDI_H__
diff --git a/include/WTL/Include/atlmisc.h b/include/WTL/Include/atlmisc.h
new file mode 100644 (file)
index 0000000..ff5e7ee
--- /dev/null
@@ -0,0 +1,4021 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLMISC_H__
+#define __ATLMISC_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlmisc.h requires atlapp.h to be included first
+#endif
+
+
+#ifdef _ATL_TMP_NO_CSTRING
+  #define _WTL_NO_CSTRING
+#endif
+
+#if defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING)
+       #error Conflicting options - both _WTL_USE_CSTRING and _WTL_NO_CSTRING are defined
+#endif // defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING)
+
+#if !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING)
+  #define _WTL_USE_CSTRING
+#endif // !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING)
+
+#ifndef _WTL_NO_CSTRING
+  #if defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT)
+       #error Cannot use CString floating point formatting with _ATL_MIN_CRT defined
+  #endif // defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT)
+#endif // !_WTL_NO_CSTRING
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CSize
+// CPoint
+// CRect
+// CString
+//
+// CRecentDocumentListBase<T, t_cchItemLen, t_nFirstID, t_nLastID>
+// CRecentDocumentList
+// CFindFile
+//
+// Global functions:
+//   AtlLoadAccelerators()
+//   AtlLoadMenu()
+//   AtlLoadBitmap()
+//   AtlLoadSysBitmap()
+//   AtlLoadCursor()
+//   AtlLoadSysCursor()
+//   AtlLoadIcon()
+//   AtlLoadSysIcon()
+//   AtlLoadBitmapImage()
+//   AtlLoadCursorImage()
+//   AtlLoadIconImage()
+//   AtlLoadSysBitmapImage()
+//   AtlLoadSysCursorImage()
+//   AtlLoadSysIconImage()
+//   AtlLoadString()
+//
+//   AtlGetStockPen()
+//   AtlGetStockBrush()
+//   AtlGetStockFont()
+//   AtlGetStockPalette()
+//
+//   AtlCompactPath()
+
+
+namespace WTL
+{
+
+#ifndef _WTL_NO_WTYPES
+
+// forward declarations
+class CSize;
+class CPoint;
+class CRect;
+
+///////////////////////////////////////////////////////////////////////////////
+// CSize - Wrapper for Windows SIZE structure.
+
+class CSize : public SIZE
+{
+public:
+// Constructors
+       CSize()
+       {
+               cx = 0;
+               cy = 0;
+       }
+
+       CSize(int initCX, int initCY)
+       {
+               cx = initCX;
+               cy = initCY;
+       }
+
+       CSize(SIZE initSize)
+       {
+               *(SIZE*)this = initSize;
+       }
+
+       CSize(POINT initPt)
+       {
+               *(POINT*)this = initPt;
+       }
+
+       CSize(DWORD dwSize)
+       {
+               cx = (short)LOWORD(dwSize);
+               cy = (short)HIWORD(dwSize);
+       }
+
+// Operations
+       BOOL operator ==(SIZE size) const
+       {
+               return (cx == size.cx && cy == size.cy);
+       }
+
+       BOOL operator !=(SIZE size) const
+       {
+               return (cx != size.cx || cy != size.cy);
+       }
+
+       void operator +=(SIZE size)
+       {
+               cx += size.cx;
+               cy += size.cy;
+       }
+
+       void operator -=(SIZE size)
+       {
+               cx -= size.cx;
+               cy -= size.cy;
+       }
+
+       void SetSize(int CX, int CY)
+       {
+               cx = CX;
+               cy = CY;
+       }
+
+// Operators returning CSize values
+       CSize operator +(SIZE size) const
+       {
+               return CSize(cx + size.cx, cy + size.cy);
+       }
+
+       CSize operator -(SIZE size) const
+       {
+               return CSize(cx - size.cx, cy - size.cy);
+       }
+
+       CSize operator -() const
+       {
+               return CSize(-cx, -cy);
+       }
+
+// Operators returning CPoint values
+       CPoint operator +(POINT point) const;
+       CPoint operator -(POINT point) const;
+
+// Operators returning CRect values
+       CRect operator +(const RECT* lpRect) const;
+       CRect operator -(const RECT* lpRect) const;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPoint - Wrapper for Windows POINT structure.
+
+class CPoint : public POINT
+{
+public:
+// Constructors
+       CPoint()
+       {
+               x = 0;
+               y = 0;
+       }
+
+       CPoint(int initX, int initY)
+       {
+               x = initX;
+               y = initY;
+       }
+
+       CPoint(POINT initPt)
+       {
+               *(POINT*)this = initPt;
+       }
+
+       CPoint(SIZE initSize)
+       {
+               *(SIZE*)this = initSize;
+       }
+
+       CPoint(DWORD dwPoint)
+       {
+               x = (short)LOWORD(dwPoint);
+               y = (short)HIWORD(dwPoint);
+       }
+
+// Operations
+       void Offset(int xOffset, int yOffset)
+       {
+               x += xOffset;
+               y += yOffset;
+       }
+
+       void Offset(POINT point)
+       {
+               x += point.x;
+               y += point.y;
+       }
+
+       void Offset(SIZE size)
+       {
+               x += size.cx;
+               y += size.cy;
+       }
+
+       BOOL operator ==(POINT point) const
+       {
+               return (x == point.x && y == point.y);
+       }
+
+       BOOL operator !=(POINT point) const
+       {
+               return (x != point.x || y != point.y);
+       }
+
+       void operator +=(SIZE size)
+       {
+               x += size.cx;
+               y += size.cy;
+       }
+
+       void operator -=(SIZE size)
+       {
+               x -= size.cx;
+               y -= size.cy;
+       }
+
+       void operator +=(POINT point)
+       {
+               x += point.x;
+               y += point.y;
+       }
+
+       void operator -=(POINT point)
+       {
+               x -= point.x;
+               y -= point.y;
+       }
+
+       void SetPoint(int X, int Y)
+       {
+               x = X;
+               y = Y;
+       }
+
+// Operators returning CPoint values
+       CPoint operator +(SIZE size) const
+       {
+               return CPoint(x + size.cx, y + size.cy);
+       }
+
+       CPoint operator -(SIZE size) const
+       {
+               return CPoint(x - size.cx, y - size.cy);
+       }
+
+       CPoint operator -() const
+       {
+               return CPoint(-x, -y);
+       }
+
+       CPoint operator +(POINT point) const
+       {
+               return CPoint(x + point.x, y + point.y);
+       }
+
+// Operators returning CSize values
+       CSize operator -(POINT point) const
+       {
+               return CSize(x - point.x, y - point.y);
+       }
+
+// Operators returning CRect values
+       CRect operator +(const RECT* lpRect) const;
+       CRect operator -(const RECT* lpRect) const;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CRect - Wrapper for Windows RECT structure.
+
+class CRect : public RECT
+{
+public:
+// Constructors
+       CRect()
+       {
+               left = 0;
+               top = 0;
+               right = 0;
+               bottom = 0;
+       }
+
+       CRect(int l, int t, int r, int b)
+       {
+               left = l;
+               top = t;
+               right = r;
+               bottom = b;
+       }
+
+       CRect(const RECT& srcRect)
+       {
+               ::CopyRect(this, &srcRect);
+       }
+
+       CRect(LPCRECT lpSrcRect)
+       {
+               ::CopyRect(this, lpSrcRect);
+       }
+
+       CRect(POINT point, SIZE size)
+       {
+               right = (left = point.x) + size.cx;
+               bottom = (top = point.y) + size.cy;
+       }
+
+       CRect(POINT topLeft, POINT bottomRight)
+       {
+               left = topLeft.x;
+               top = topLeft.y;
+               right = bottomRight.x;
+               bottom = bottomRight.y;
+       }
+
+// Attributes (in addition to RECT members)
+       int Width() const
+       {
+               return right - left;
+       }
+
+       int Height() const
+       {
+               return bottom - top;
+       }
+
+       CSize Size() const
+       {
+               return CSize(right - left, bottom - top);
+       }
+
+       CPoint& TopLeft()
+       {
+               return *((CPoint*)this);
+       }
+
+       CPoint& BottomRight()
+       {
+               return *((CPoint*)this + 1);
+       }
+
+       const CPoint& TopLeft() const
+       {
+               return *((CPoint*)this);
+       }
+
+       const CPoint& BottomRight() const
+       {
+               return *((CPoint*)this + 1);
+       }
+
+       CPoint CenterPoint() const
+       {
+               return CPoint((left + right) / 2, (top + bottom) / 2);
+       }
+
+       // convert between CRect and LPRECT/LPCRECT (no need for &)
+       operator LPRECT()
+       {
+               return this;
+       }
+
+       operator LPCRECT() const
+       {
+               return this;
+       }
+
+       BOOL IsRectEmpty() const
+       {
+               return ::IsRectEmpty(this);
+       }
+
+       BOOL IsRectNull() const
+       {
+               return (left == 0 && right == 0 && top == 0 && bottom == 0);
+       }
+
+       BOOL PtInRect(POINT point) const
+       {
+               return ::PtInRect(this, point);
+       }
+
+// Operations
+       void SetRect(int x1, int y1, int x2, int y2)
+       {
+               ::SetRect(this, x1, y1, x2, y2);
+       }
+
+       void SetRect(POINT topLeft, POINT bottomRight)
+       {
+               ::SetRect(this, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
+       }
+
+       void SetRectEmpty()
+       {
+               ::SetRectEmpty(this);
+       }
+
+       void CopyRect(LPCRECT lpSrcRect)
+       {
+               ::CopyRect(this, lpSrcRect);
+       }
+
+       BOOL EqualRect(LPCRECT lpRect) const
+       {
+               return ::EqualRect(this, lpRect);
+       }
+
+       void InflateRect(int x, int y)
+       {
+               ::InflateRect(this, x, y);
+       }
+
+       void InflateRect(SIZE size)
+       {
+               ::InflateRect(this, size.cx, size.cy);
+       }
+
+       void InflateRect(LPCRECT lpRect)
+       {
+               left -= lpRect->left;
+               top -= lpRect->top;
+               right += lpRect->right;
+               bottom += lpRect->bottom;
+       }
+
+       void InflateRect(int l, int t, int r, int b)
+       {
+               left -= l;
+               top -= t;
+               right += r;
+               bottom += b;
+       }
+
+       void DeflateRect(int x, int y)
+       {
+               ::InflateRect(this, -x, -y);
+       }
+
+       void DeflateRect(SIZE size)
+       {
+               ::InflateRect(this, -size.cx, -size.cy);
+       }
+
+       void DeflateRect(LPCRECT lpRect)
+       {
+               left += lpRect->left;
+               top += lpRect->top;
+               right -= lpRect->right;
+               bottom -= lpRect->bottom;
+       }
+
+       void DeflateRect(int l, int t, int r, int b)
+       {
+               left += l;
+               top += t;
+               right -= r;
+               bottom -= b;
+       }
+
+       void OffsetRect(int x, int y)
+       {
+               ::OffsetRect(this, x, y);
+       }
+       void OffsetRect(SIZE size)
+       {
+               ::OffsetRect(this, size.cx, size.cy);
+       }
+
+       void OffsetRect(POINT point)
+       {
+               ::OffsetRect(this, point.x, point.y);
+       }
+
+       void NormalizeRect()
+       {
+               int nTemp;
+               if (left > right)
+               {
+                       nTemp = left;
+                       left = right;
+                       right = nTemp;
+               }
+               if (top > bottom)
+               {
+                       nTemp = top;
+                       top = bottom;
+                       bottom = nTemp;
+               }
+       }
+
+       // absolute position of rectangle
+       void MoveToY(int y)
+       {
+               bottom = Height() + y;
+               top = y;
+       }
+
+       void MoveToX(int x)
+       {
+               right = Width() + x;
+               left = x;
+       }
+
+       void MoveToXY(int x, int y)
+       {
+               MoveToX(x);
+               MoveToY(y);
+       }
+
+       void MoveToXY(POINT pt)
+       {
+               MoveToX(pt.x);
+               MoveToY(pt.y);
+       }
+
+       // operations that fill '*this' with result
+       BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2)
+       {
+               return ::IntersectRect(this, lpRect1, lpRect2);
+       }
+
+       BOOL UnionRect(LPCRECT lpRect1, LPCRECT lpRect2)
+       {
+               return ::UnionRect(this, lpRect1, lpRect2);
+       }
+
+       BOOL SubtractRect(LPCRECT lpRectSrc1, LPCRECT lpRectSrc2)
+       {
+               return ::SubtractRect(this, lpRectSrc1, lpRectSrc2);
+       }
+
+// Additional Operations
+       void operator =(const RECT& srcRect)
+       {
+               ::CopyRect(this, &srcRect);
+       }
+
+       BOOL operator ==(const RECT& rect) const
+       {
+               return ::EqualRect(this, &rect);
+       }
+
+       BOOL operator !=(const RECT& rect) const
+       {
+               return !::EqualRect(this, &rect);
+       }
+
+       void operator +=(POINT point)
+       {
+               ::OffsetRect(this, point.x, point.y);
+       }
+
+       void operator +=(SIZE size)
+       {
+               ::OffsetRect(this, size.cx, size.cy);
+       }
+
+       void operator +=(LPCRECT lpRect)
+       {
+               InflateRect(lpRect);
+       }
+
+       void operator -=(POINT point)
+       {
+               ::OffsetRect(this, -point.x, -point.y);
+       }
+
+       void operator -=(SIZE size)
+       {
+               ::OffsetRect(this, -size.cx, -size.cy);
+       }
+
+       void operator -=(LPCRECT lpRect)
+       {
+               DeflateRect(lpRect);
+       }
+
+       void operator &=(const RECT& rect)
+       {
+               ::IntersectRect(this, this, &rect);
+       }
+
+       void operator |=(const RECT& rect)
+       {
+               ::UnionRect(this, this, &rect);
+       }
+
+// Operators returning CRect values
+       CRect operator +(POINT pt) const
+       {
+               CRect rect(*this);
+               ::OffsetRect(&rect, pt.x, pt.y);
+               return rect;
+       }
+
+       CRect operator -(POINT pt) const
+       {
+               CRect rect(*this);
+               ::OffsetRect(&rect, -pt.x, -pt.y);
+               return rect;
+       }
+
+       CRect operator +(LPCRECT lpRect) const
+       {
+               CRect rect(this);
+               rect.InflateRect(lpRect);
+               return rect;
+       }
+
+       CRect operator +(SIZE size) const
+       {
+               CRect rect(*this);
+               ::OffsetRect(&rect, size.cx, size.cy);
+               return rect;
+       }
+
+       CRect operator -(SIZE size) const
+       {
+               CRect rect(*this);
+               ::OffsetRect(&rect, -size.cx, -size.cy);
+               return rect;
+       }
+
+       CRect operator -(LPCRECT lpRect) const
+       {
+               CRect rect(this);
+               rect.DeflateRect(lpRect);
+               return rect;
+       }
+
+       CRect operator &(const RECT& rect2) const
+       {
+               CRect rect;
+               ::IntersectRect(&rect, this, &rect2);
+               return rect;
+       }
+
+       CRect operator |(const RECT& rect2) const
+       {
+               CRect rect;
+               ::UnionRect(&rect, this, &rect2);
+               return rect;
+       }
+
+       CRect MulDiv(int nMultiplier, int nDivisor) const
+       {
+               return CRect(
+                       ::MulDiv(left, nMultiplier, nDivisor),
+                       ::MulDiv(top, nMultiplier, nDivisor),
+                       ::MulDiv(right, nMultiplier, nDivisor),
+                       ::MulDiv(bottom, nMultiplier, nDivisor));
+       }
+};
+
+
+// CSize implementation
+
+inline CPoint CSize::operator +(POINT point) const
+{ return CPoint(cx + point.x, cy + point.y); }
+
+inline CPoint CSize::operator -(POINT point) const
+{ return CPoint(cx - point.x, cy - point.y); }
+
+inline CRect CSize::operator +(const RECT* lpRect) const
+{ return CRect(lpRect) + *this; }
+
+inline CRect CSize::operator -(const RECT* lpRect) const
+{ return CRect(lpRect) - *this; }
+
+
+// CPoint implementation
+
+inline CRect CPoint::operator +(const RECT* lpRect) const
+{ return CRect(lpRect) + *this; }
+
+inline CRect CPoint::operator -(const RECT* lpRect) const
+{ return CRect(lpRect) - *this; }
+
+#endif // !_WTL_NO_WTYPES
+
+
+// WTL::CSize or ATL::CSize scalar operators 
+
+#if !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__))
+
+template <class Num>
+inline CSize operator *(SIZE s, Num n) 
+{
+       return CSize((int)(s.cx * n), (int)(s.cy * n));
+};
+
+template <class Num>
+inline void operator *=(SIZE & s, Num n)
+{
+       s = s * n;
+};     
+
+template <class Num>
+inline CSize operator /(SIZE s, Num n) 
+{
+       return CSize((int)(s.cx / n), (int)(s.cy / n));
+};
+
+template <class Num>
+inline void operator /=(SIZE & s, Num n)
+{
+       s = s / n;
+};     
+
+#endif // !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__))
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CString - String class
+
+#ifndef _WTL_NO_CSTRING
+
+struct CStringData
+{
+       long nRefs;     // reference count
+       int nDataLength;
+       int nAllocLength;
+       // TCHAR data[nAllocLength]
+
+       TCHAR* data()
+       { return (TCHAR*)(this + 1); }
+};
+
+// Globals
+
+// For an empty string, m_pchData will point here
+// (note: avoids special case of checking for NULL m_pchData)
+// empty string data (and locked)
+_declspec(selectany) int rgInitData[] = { -1, 0, 0, 0 };
+_declspec(selectany) CStringData* _atltmpDataNil = (CStringData*)&rgInitData;
+_declspec(selectany) LPCTSTR _atltmpPchNil = (LPCTSTR)(((BYTE*)&rgInitData) + sizeof(CStringData));
+
+
+class CString
+{
+public:
+// Constructors
+       CString()
+       {
+               Init();
+       }
+
+       CString(const CString& stringSrc)
+       {
+               ATLASSERT(stringSrc.GetData()->nRefs != 0);
+               if (stringSrc.GetData()->nRefs >= 0)
+               {
+                       ATLASSERT(stringSrc.GetData() != _atltmpDataNil);
+                       m_pchData = stringSrc.m_pchData;
+                       InterlockedIncrement(&GetData()->nRefs);
+               }
+               else
+               {
+                       Init();
+                       *this = stringSrc.m_pchData;
+               }
+       }
+
+       CString(TCHAR ch, int nRepeat = 1)
+       {
+               ATLASSERT(!_istlead(ch));   // can't create a lead byte string
+               Init();
+               if (nRepeat >= 1)
+               {
+                       if(AllocBuffer(nRepeat))
+                       {
+#ifdef _UNICODE
+                               for (int i = 0; i < nRepeat; i++)
+                                       m_pchData[i] = ch;
+#else
+                               memset(m_pchData, ch, nRepeat);
+#endif
+                       }
+               }
+       }
+
+       CString(LPCTSTR lpsz)
+       {
+               Init();
+               if (lpsz != NULL && HIWORD(lpsz) == NULL)
+               {
+                       UINT nID = LOWORD((DWORD_PTR)lpsz);
+                       if (!LoadString(nID))
+                               ATLTRACE2(atlTraceUI, 0, _T("Warning: implicit LoadString(%u) in CString failed\n"), nID);
+               }
+               else
+               {
+                       int nLen = SafeStrlen(lpsz);
+                       if (nLen != 0)
+                       {
+                               if(AllocBuffer(nLen))
+                                       SecureHelper::memcpy_x(m_pchData, (nLen + 1) * sizeof(TCHAR), lpsz, nLen * sizeof(TCHAR));
+                       }
+               }
+       }
+
+#ifdef _UNICODE
+       CString(LPCSTR lpsz)
+       {
+               Init();
+#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
+               int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0;
+#else
+               int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0;
+#endif
+               if (nSrcLen != 0)
+               {
+                       if(AllocBuffer(nSrcLen))
+                       {
+                               _mbstowcsz(m_pchData, lpsz, nSrcLen + 1);
+                               ReleaseBuffer();
+                       }
+               }
+       }
+#else // !_UNICODE
+       CString(LPCWSTR lpsz)
+       {
+               Init();
+               int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0;
+               if (nSrcLen != 0)
+               {
+                       if(AllocBuffer(nSrcLen * 2))
+                       {
+                               _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1);
+                               ReleaseBuffer();
+                       }
+               }
+       }
+#endif // !_UNICODE
+
+       CString(LPCTSTR lpch, int nLength)
+       {
+               Init();
+               if (nLength != 0)
+               {
+                       if(AllocBuffer(nLength))
+                               SecureHelper::memcpy_x(m_pchData, (nLength + 1) * sizeof(TCHAR), lpch, nLength * sizeof(TCHAR));
+               }
+       }
+
+#ifdef _UNICODE
+       CString(LPCSTR lpsz, int nLength)
+       {
+               Init();
+               if (nLength != 0)
+               {
+                       if(AllocBuffer(nLength))
+                       {
+                               int n = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nLength, m_pchData, nLength + 1);
+                               ReleaseBuffer((n >= 0) ? n : -1);
+                       }
+               }
+       }
+#else // !_UNICODE
+       CString(LPCWSTR lpsz, int nLength)
+       {
+               Init();
+               if (nLength != 0)
+               {
+                       if(((nLength * 2) > nLength) && AllocBuffer(nLength * 2))
+                       {
+                               int n = ::WideCharToMultiByte(CP_ACP, 0, lpsz, nLength, m_pchData, (nLength * 2) + 1, NULL, NULL);
+                               ReleaseBuffer((n >= 0) ? n : -1);
+                       }
+               }
+       }
+#endif // !_UNICODE
+
+       CString(const unsigned char* lpsz)
+       {
+               Init();
+               *this = (LPCSTR)lpsz;
+       }
+
+// Attributes & Operations
+       int GetLength() const   // as an array of characters
+       {
+               return GetData()->nDataLength;
+       }
+
+       BOOL IsEmpty() const
+       {
+               return GetData()->nDataLength == 0;
+       }
+
+       void Empty()   // free up the data
+       {
+               if (GetData()->nDataLength == 0)
+                       return;
+
+               if (GetData()->nRefs >= 0)
+                       Release();
+               else
+                       *this = _T("");
+
+               ATLASSERT(GetData()->nDataLength == 0);
+               ATLASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0);
+       }
+
+       TCHAR GetAt(int nIndex) const   // 0 based
+       {
+               ATLASSERT(nIndex >= 0);
+               ATLASSERT(nIndex < GetData()->nDataLength);
+               return m_pchData[nIndex];
+       }
+
+       TCHAR operator [](int nIndex) const   // same as GetAt
+       {
+               // same as GetAt
+               ATLASSERT(nIndex >= 0);
+               ATLASSERT(nIndex < GetData()->nDataLength);
+               return m_pchData[nIndex];
+       }
+
+       void SetAt(int nIndex, TCHAR ch)
+       {
+               ATLASSERT(nIndex >= 0);
+               ATLASSERT(nIndex < GetData()->nDataLength);
+
+               CopyBeforeWrite();
+               m_pchData[nIndex] = ch;
+       }
+
+       operator LPCTSTR() const   // as a C string
+       {
+               return m_pchData;
+       }
+
+       // overloaded assignment
+       CString& operator =(const CString& stringSrc)
+       {
+               if (m_pchData != stringSrc.m_pchData)
+               {
+                       if ((GetData()->nRefs < 0 && GetData() != _atltmpDataNil) || stringSrc.GetData()->nRefs < 0)
+                       {
+                               // actual copy necessary since one of the strings is locked
+                               AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
+                       }
+                       else
+                       {
+                               // can just copy references around
+                               Release();
+                               ATLASSERT(stringSrc.GetData() != _atltmpDataNil);
+                               m_pchData = stringSrc.m_pchData;
+                               InterlockedIncrement(&GetData()->nRefs);
+                       }
+               }
+               return *this;
+       }
+
+       CString& operator =(TCHAR ch)
+       {
+               ATLASSERT(!_istlead(ch));   // can't set single lead byte
+               AssignCopy(1, &ch);
+               return *this;
+       }
+
+#ifdef _UNICODE
+       CString& operator =(char ch)
+       {
+               *this = (TCHAR)ch;
+               return *this;
+       }
+#endif
+
+       CString& operator =(LPCTSTR lpsz)
+       {
+               ATLASSERT(lpsz == NULL || _IsValidString(lpsz));
+               AssignCopy(SafeStrlen(lpsz), lpsz);
+               return *this;
+       }
+
+#ifdef _UNICODE
+       CString& operator =(LPCSTR lpsz)
+       {
+#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
+               int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0;
+#else
+               int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0;
+#endif
+               if(AllocBeforeWrite(nSrcLen))
+               {
+                       _mbstowcsz(m_pchData, lpsz, nSrcLen + 1);
+                       ReleaseBuffer();
+               }
+               return *this;
+       }
+#else // !_UNICODE
+       CString& operator =(LPCWSTR lpsz)
+       {
+               int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0;
+               if(AllocBeforeWrite(nSrcLen * 2))
+               {
+                       _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1);
+                       ReleaseBuffer();
+               }
+               return *this;
+       }
+#endif  // !_UNICODE
+
+       CString& operator =(const unsigned char* lpsz)
+       {
+               *this = (LPCSTR)lpsz;
+               return *this;
+       }
+
+       // string concatenation
+       CString& operator +=(const CString& string)
+       {
+               ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
+               return *this;
+       }
+
+       CString& operator +=(TCHAR ch)
+       {
+               ConcatInPlace(1, &ch);
+               return *this;
+       }
+
+#ifdef _UNICODE
+       CString& operator +=(char ch)
+       {
+               *this += (TCHAR)ch;
+               return *this;
+       }
+#endif
+
+       CString& operator +=(LPCTSTR lpsz)
+       {
+               ATLASSERT(lpsz == NULL || _IsValidString(lpsz));
+               ConcatInPlace(SafeStrlen(lpsz), lpsz);
+               return *this;
+       }
+
+       friend CString __stdcall operator +(const CString& string1, const CString& string2);
+       friend CString __stdcall operator +(const CString& string, TCHAR ch);
+       friend CString __stdcall operator +(TCHAR ch, const CString& string);
+#ifdef _UNICODE
+       friend CString __stdcall operator +(const CString& string, char ch);
+       friend CString __stdcall operator +(char ch, const CString& string);
+#endif
+       friend CString __stdcall operator +(const CString& string, LPCTSTR lpsz);
+       friend CString __stdcall operator +(LPCTSTR lpsz, const CString& string);
+
+       // string comparison
+       int Compare(LPCTSTR lpsz) const   // straight character (MBCS/Unicode aware)
+       {
+               return _cstrcmp(m_pchData, lpsz);
+       }
+
+       int CompareNoCase(LPCTSTR lpsz) const   // ignore case (MBCS/Unicode aware)
+       {
+               return _cstrcmpi(m_pchData, lpsz);
+       }
+
+#ifndef _WIN32_WCE
+       // CString::Collate is often slower than Compare but is MBSC/Unicode
+       //  aware as well as locale-sensitive with respect to sort order.
+       int Collate(LPCTSTR lpsz) const   // NLS aware
+       {
+               return _cstrcoll(m_pchData, lpsz);
+       }
+
+       int CollateNoCase(LPCTSTR lpsz) const   // ignore case
+       {
+               return _cstrcolli(m_pchData, lpsz);
+       }
+#endif // !_WIN32_WCE
+
+       // simple sub-string extraction
+       CString Mid(int nFirst, int nCount) const
+       {
+               // out-of-bounds requests return sensible things
+               if (nFirst < 0)
+                       nFirst = 0;
+               if (nCount < 0)
+                       nCount = 0;
+
+               if (nFirst + nCount > GetData()->nDataLength)
+                       nCount = GetData()->nDataLength - nFirst;
+               if (nFirst > GetData()->nDataLength)
+                       nCount = 0;
+
+               CString dest;
+               AllocCopy(dest, nCount, nFirst, 0);
+               return dest;
+       }
+
+       CString Mid(int nFirst) const
+       {
+               return Mid(nFirst, GetData()->nDataLength - nFirst);
+       }
+
+       CString Left(int nCount) const
+       {
+               if (nCount < 0)
+                       nCount = 0;
+               else if (nCount > GetData()->nDataLength)
+                       nCount = GetData()->nDataLength;
+
+               CString dest;
+               AllocCopy(dest, nCount, 0, 0);
+               return dest;
+       }
+
+       CString Right(int nCount) const
+       {
+               if (nCount < 0)
+                       nCount = 0;
+               else if (nCount > GetData()->nDataLength)
+                       nCount = GetData()->nDataLength;
+
+               CString dest;
+               AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
+               return dest;
+       }
+
+       CString SpanIncluding(LPCTSTR lpszCharSet) const   // strspn equivalent
+       {
+               ATLASSERT(_IsValidString(lpszCharSet));
+               return Left(_cstrspn(m_pchData, lpszCharSet));
+       }
+
+       CString SpanExcluding(LPCTSTR lpszCharSet) const   // strcspn equivalent
+       {
+               ATLASSERT(_IsValidString(lpszCharSet));
+               return Left(_cstrcspn(m_pchData, lpszCharSet));
+       }
+
+       // upper/lower/reverse conversion
+       void MakeUpper()
+       {
+               CopyBeforeWrite();
+               CharUpper(m_pchData);
+       }
+
+       void MakeLower()
+       {
+               CopyBeforeWrite();
+               CharLower(m_pchData);
+       }
+
+       void MakeReverse()
+       {
+               CopyBeforeWrite();
+               _cstrrev(m_pchData);
+       }
+
+       // trimming whitespace (either side)
+       void TrimRight()
+       {
+               CopyBeforeWrite();
+
+               // find beginning of trailing spaces by starting at beginning (DBCS aware)
+               LPTSTR lpsz = m_pchData;
+               LPTSTR lpszLast = NULL;
+               while (*lpsz != _T('\0'))
+               {
+                       if (_cstrisspace(*lpsz))
+                       {
+                               if (lpszLast == NULL)
+                                       lpszLast = lpsz;
+                       }
+                       else
+                       {
+                               lpszLast = NULL;
+                       }
+                       lpsz = ::CharNext(lpsz);
+               }
+
+               if (lpszLast != NULL)
+               {
+                       // truncate at trailing space start
+                       *lpszLast = _T('\0');
+                       GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData);
+               }
+       }
+
+       void TrimLeft()
+       {
+               CopyBeforeWrite();
+
+               // find first non-space character
+               LPCTSTR lpsz = m_pchData;
+               while (_cstrisspace(*lpsz))
+                       lpsz = ::CharNext(lpsz);
+
+               // fix up data and length
+               int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData);
+               SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR));
+               GetData()->nDataLength = nDataLength;
+       }
+
+       // remove continuous occurrences of chTarget starting from right
+       void TrimRight(TCHAR chTarget)
+       {
+               // find beginning of trailing matches
+               // by starting at beginning (DBCS aware)
+
+               CopyBeforeWrite();
+               LPTSTR lpsz = m_pchData;
+               LPTSTR lpszLast = NULL;
+
+               while (*lpsz != _T('\0'))
+               {
+                       if (*lpsz == chTarget)
+                       {
+                               if (lpszLast == NULL)
+                                       lpszLast = lpsz;
+                       }
+                       else
+                               lpszLast = NULL;
+                       lpsz = ::CharNext(lpsz);
+               }
+
+               if (lpszLast != NULL)
+               {
+                       // truncate at left-most matching character
+                       *lpszLast = _T('\0');
+                       GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData);
+               }
+       }
+
+       // remove continuous occcurrences of characters in passed string, starting from right
+       void TrimRight(LPCTSTR lpszTargetList)
+       {
+               // find beginning of trailing matches by starting at beginning (DBCS aware)
+
+               CopyBeforeWrite();
+               LPTSTR lpsz = m_pchData;
+               LPTSTR lpszLast = NULL;
+
+               while (*lpsz != _T('\0'))
+               {
+                       TCHAR* pNext = ::CharNext(lpsz);
+                       if(pNext > lpsz + 1)
+                       {
+                               if (_cstrchr_db(lpszTargetList, *lpsz, *(lpsz + 1)) != NULL)
+                               {
+                                       if (lpszLast == NULL)
+                                               lpszLast = lpsz;
+                               }
+                               else
+                               {
+                                       lpszLast = NULL;
+                               }
+                       }
+                       else
+                       {
+                               if (_cstrchr(lpszTargetList, *lpsz) != NULL)
+                               {
+                                       if (lpszLast == NULL)
+                                               lpszLast = lpsz;
+                               }
+                               else
+                               {
+                                       lpszLast = NULL;
+                               }
+                       }
+
+                       lpsz = pNext;
+               }
+
+               if (lpszLast != NULL)
+               {
+                       // truncate at left-most matching character
+                       *lpszLast = _T('\0');
+                       GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData);
+               }
+       }
+
+       // remove continuous occurrences of chTarget starting from left
+       void TrimLeft(TCHAR chTarget)
+       {
+               // find first non-matching character
+
+               CopyBeforeWrite();
+               LPCTSTR lpsz = m_pchData;
+
+               while (chTarget == *lpsz)
+                       lpsz = ::CharNext(lpsz);
+
+               if (lpsz != m_pchData)
+               {
+                       // fix up data and length
+                       int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData);
+                       SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR));
+                       GetData()->nDataLength = nDataLength;
+               }
+       }
+
+       // remove continuous occcurrences of characters in passed string, starting from left
+       void TrimLeft(LPCTSTR lpszTargets)
+       {
+               // if we're not trimming anything, we're not doing any work
+               if (SafeStrlen(lpszTargets) == 0)
+                       return;
+
+               CopyBeforeWrite();
+               LPCTSTR lpsz = m_pchData;
+
+               while (*lpsz != _T('\0'))
+               {
+                       TCHAR* pNext = ::CharNext(lpsz);
+                       if(pNext > lpsz + 1)
+                       {
+                               if (_cstrchr_db(lpszTargets, *lpsz, *(lpsz + 1)) == NULL)
+                                       break;
+                       }
+                       else
+                       {
+                               if (_cstrchr(lpszTargets, *lpsz) == NULL)
+                                       break;
+                       }
+                       lpsz = pNext;
+               }
+
+               if (lpsz != m_pchData)
+               {
+                       // fix up data and length
+                       int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData);
+                       SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR));
+                       GetData()->nDataLength = nDataLength;
+               }
+       }
+
+       // advanced manipulation
+       // replace occurrences of chOld with chNew
+       int Replace(TCHAR chOld, TCHAR chNew)
+       {
+               int nCount = 0;
+
+               // short-circuit the nop case
+               if (chOld != chNew)
+               {
+                       // otherwise modify each character that matches in the string
+                       CopyBeforeWrite();
+                       LPTSTR psz = m_pchData;
+                       LPTSTR pszEnd = psz + GetData()->nDataLength;
+                       while (psz < pszEnd)
+                       {
+                               // replace instances of the specified character only
+                               if (*psz == chOld)
+                               {
+                                       *psz = chNew;
+                                       nCount++;
+                               }
+                               psz = ::CharNext(psz);
+                       }
+               }
+               return nCount;
+       }
+
+       // replace occurrences of substring lpszOld with lpszNew;
+       // empty lpszNew removes instances of lpszOld
+       int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew)
+       {
+               // can't have empty or NULL lpszOld
+
+               int nSourceLen = SafeStrlen(lpszOld);
+               if (nSourceLen == 0)
+                       return 0;
+               int nReplacementLen = SafeStrlen(lpszNew);
+
+               // loop once to figure out the size of the result string
+               int nCount = 0;
+               LPTSTR lpszStart = m_pchData;
+               LPTSTR lpszEnd = m_pchData + GetData()->nDataLength;
+               LPTSTR lpszTarget = NULL;
+               while (lpszStart < lpszEnd)
+               {
+                       while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL)
+                       {
+                               nCount++;
+                               lpszStart = lpszTarget + nSourceLen;
+                       }
+                       lpszStart += lstrlen(lpszStart) + 1;
+               }
+
+               // if any changes were made, make them
+               if (nCount > 0)
+               {
+                       CopyBeforeWrite();
+
+                       // if the buffer is too small, just allocate a new buffer (slow but sure)
+                       int nOldLength = GetData()->nDataLength;
+                       int nNewLength =  nOldLength + (nReplacementLen - nSourceLen) * nCount;
+                       if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1)
+                       {
+                               CStringData* pOldData = GetData();
+                               LPTSTR pstr = m_pchData;
+                               if(!AllocBuffer(nNewLength))
+                                       return -1;
+                               SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, pOldData->nDataLength * sizeof(TCHAR));
+                               CString::Release(pOldData);
+                       }
+                       // else, we just do it in-place
+                       lpszStart = m_pchData;
+                       lpszEnd = m_pchData + GetData()->nDataLength;
+
+                       // loop again to actually do the work
+                       while (lpszStart < lpszEnd)
+                       {
+                               while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL)
+                               {
+                                       int nBalance = nOldLength - ((int)(DWORD_PTR)(lpszTarget - m_pchData) + nSourceLen);
+                                       int cchBuffLen = GetData()->nAllocLength - (int)(DWORD_PTR)(lpszTarget - m_pchData);
+                                       SecureHelper::memmove_x(lpszTarget + nReplacementLen, (cchBuffLen - nReplacementLen + 1) * sizeof(TCHAR), lpszTarget + nSourceLen, nBalance * sizeof(TCHAR));
+                                       SecureHelper::memcpy_x(lpszTarget, (cchBuffLen + 1) * sizeof(TCHAR), lpszNew, nReplacementLen * sizeof(TCHAR));
+                                       lpszStart = lpszTarget + nReplacementLen;
+                                       lpszStart[nBalance] = _T('\0');
+                                       nOldLength += (nReplacementLen - nSourceLen);
+                               }
+                               lpszStart += lstrlen(lpszStart) + 1;
+                       }
+                       ATLASSERT(m_pchData[nNewLength] == _T('\0'));
+                       GetData()->nDataLength = nNewLength;
+               }
+
+               return nCount;
+       }
+
+       // remove occurrences of chRemove
+       int Remove(TCHAR chRemove)
+       {
+               CopyBeforeWrite();
+
+               LPTSTR pstrSource = m_pchData;
+               LPTSTR pstrDest = m_pchData;
+               LPTSTR pstrEnd = m_pchData + GetData()->nDataLength;
+
+               while (pstrSource < pstrEnd)
+               {
+                       if (*pstrSource != chRemove)
+                       {
+                               *pstrDest = *pstrSource;
+                               pstrDest = ::CharNext(pstrDest);
+                       }
+                       pstrSource = ::CharNext(pstrSource);
+               }
+               *pstrDest = _T('\0');
+               int nCount = (int)(DWORD_PTR)(pstrSource - pstrDest);
+               GetData()->nDataLength -= nCount;
+
+               return nCount;
+       }
+
+       // insert character at zero-based index; concatenates if index is past end of string
+       int Insert(int nIndex, TCHAR ch)
+       {
+               CopyBeforeWrite();
+
+               if (nIndex < 0)
+                       nIndex = 0;
+
+               int nNewLength = GetData()->nDataLength;
+               if (nIndex > nNewLength)
+                       nIndex = nNewLength;
+               nNewLength++;
+
+               if (GetData()->nAllocLength < nNewLength)
+               {
+                       CStringData* pOldData = GetData();
+                       LPTSTR pstr = m_pchData;
+                       if(!AllocBuffer(nNewLength))
+                               return -1;
+                       SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR));
+                       CString::Release(pOldData);
+               }
+
+               // move existing bytes down
+               SecureHelper::memmove_x(m_pchData + nIndex + 1, (GetData()->nAllocLength - nIndex) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex) * sizeof(TCHAR));
+               m_pchData[nIndex] = ch;
+               GetData()->nDataLength = nNewLength;
+
+               return nNewLength;
+       }
+
+       // insert substring at zero-based index; concatenates if index is past end of string
+       int Insert(int nIndex, LPCTSTR pstr)
+       {
+               if (nIndex < 0)
+                       nIndex = 0;
+
+               int nInsertLength = SafeStrlen(pstr);
+               int nNewLength = GetData()->nDataLength;
+               if (nInsertLength > 0)
+               {
+                       CopyBeforeWrite();
+                       if (nIndex > nNewLength)
+                               nIndex = nNewLength;
+                       nNewLength += nInsertLength;
+
+                       if (GetData()->nAllocLength < nNewLength)
+                       {
+                               CStringData* pOldData = GetData();
+                               LPTSTR pstr = m_pchData;
+                               if(!AllocBuffer(nNewLength))
+                                       return -1;
+                               SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR));
+                               CString::Release(pOldData);
+                       }
+
+                       // move existing bytes down
+                       SecureHelper::memmove_x(m_pchData + nIndex + nInsertLength, (GetData()->nAllocLength + 1 - nIndex - nInsertLength) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex - nInsertLength + 1) * sizeof(TCHAR));
+                       SecureHelper::memcpy_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), pstr, nInsertLength * sizeof(TCHAR));
+                       GetData()->nDataLength = nNewLength;
+               }
+
+               return nNewLength;
+       }
+
+       // delete nCount characters starting at zero-based index
+       int Delete(int nIndex, int nCount = 1)
+       {
+               if (nIndex < 0)
+                       nIndex = 0;
+               int nLength = GetData()->nDataLength;
+               if (nCount > 0 && nIndex < nLength)
+               {
+                       if((nIndex + nCount) > nLength)
+                               nCount = nLength - nIndex;
+                       CopyBeforeWrite();
+                       int nBytesToCopy = nLength - (nIndex + nCount) + 1;
+
+                       SecureHelper::memmove_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR));
+                       nLength -= nCount;
+                       GetData()->nDataLength = nLength;
+               }
+
+               return nLength;
+       }
+
+       // searching (return starting index, or -1 if not found)
+       // look for a single character match
+       int Find(TCHAR ch) const   // like "C" strchr
+       {
+               return Find(ch, 0);
+       }
+
+       int ReverseFind(TCHAR ch) const
+       {
+               // find last single character
+               LPCTSTR lpsz = _cstrrchr(m_pchData, (_TUCHAR)ch);
+
+               // return -1 if not found, distance from beginning otherwise
+               return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
+       }
+
+       int Find(TCHAR ch, int nStart) const   // starting at index
+       {
+               int nLength = GetData()->nDataLength;
+               if (nStart < 0 || nStart >= nLength)
+                       return -1;
+
+               // find first single character
+               LPCTSTR lpsz = _cstrchr(m_pchData + nStart, (_TUCHAR)ch);
+
+               // return -1 if not found and index otherwise
+               return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
+       }
+
+       int FindOneOf(LPCTSTR lpszCharSet) const
+       {
+               ATLASSERT(_IsValidString(lpszCharSet));
+               LPCTSTR lpsz = _cstrpbrk(m_pchData, lpszCharSet);
+               return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
+       }
+
+       // look for a specific sub-string
+       // find a sub-string (like strstr)
+       int Find(LPCTSTR lpszSub) const   // like "C" strstr
+       {
+               return Find(lpszSub, 0);
+       }
+
+       int Find(LPCTSTR lpszSub, int nStart) const   // starting at index
+       {
+               ATLASSERT(_IsValidString(lpszSub));
+
+               int nLength = GetData()->nDataLength;
+               if (nStart < 0 || nStart > nLength)
+                       return -1;
+
+               // find first matching substring
+               LPCTSTR lpsz = _cstrstr(m_pchData + nStart, lpszSub);
+
+               // return -1 for not found, distance from beginning otherwise
+               return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
+       }
+
+       // Concatentation for non strings
+       CString& Append(int n)
+       {
+               const int cchBuff = 12;
+               TCHAR szBuffer[cchBuff] = { 0 };
+               SecureHelper::wsprintf_x(szBuffer, cchBuff, _T("%d"), n);
+               ConcatInPlace(SafeStrlen(szBuffer), szBuffer);
+               return *this;
+       }
+
+       // simple formatting
+       // formatting (using wsprintf style formatting)
+       BOOL __cdecl Format(LPCTSTR lpszFormat, ...)
+       {
+               ATLASSERT(_IsValidString(lpszFormat));
+
+               va_list argList;
+               va_start(argList, lpszFormat);
+               BOOL bRet = FormatV(lpszFormat, argList);
+               va_end(argList);
+               return bRet;
+       }
+
+       BOOL __cdecl Format(UINT nFormatID, ...)
+       {
+               CString strFormat;
+               BOOL bRet = strFormat.LoadString(nFormatID);
+               ATLASSERT(bRet != 0);
+
+               va_list argList;
+               va_start(argList, nFormatID);
+               bRet = FormatV(strFormat, argList);
+               va_end(argList);
+               return bRet;
+       }
+
+       BOOL FormatV(LPCTSTR lpszFormat, va_list argList)
+       {
+               ATLASSERT(_IsValidString(lpszFormat));
+
+               enum _FormatModifiers
+               {
+                       FORCE_ANSI =    0x10000,
+                       FORCE_UNICODE = 0x20000,
+                       FORCE_INT64 =   0x40000
+               };
+
+               va_list argListSave = argList;
+
+               // make a guess at the maximum length of the resulting string
+               int nMaxLen = 0;
+               for (LPCTSTR lpsz = lpszFormat; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz))
+               {
+                       // handle '%' character, but watch out for '%%'
+                       if (*lpsz != _T('%') || *(lpsz = ::CharNext(lpsz)) == _T('%'))
+                       {
+                               nMaxLen += (int)(::CharNext(lpsz) - lpsz);
+                               continue;
+                       }
+
+                       int nItemLen = 0;
+
+                       // handle '%' character with format
+                       int nWidth = 0;
+                       for (; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz))
+                       {
+                               // check for valid flags
+                               if (*lpsz == _T('#'))
+                                       nMaxLen += 2;   // for '0x'
+                               else if (*lpsz == _T('*'))
+                                       nWidth = va_arg(argList, int);
+                               else if (*lpsz == _T('-') || *lpsz == _T('+') || *lpsz == _T('0') || *lpsz == _T(' '))
+                                       ;
+                               else // hit non-flag character
+                                       break;
+                       }
+                       // get width and skip it
+                       if (nWidth == 0)
+                       {
+                               // width indicated by
+                               nWidth = _cstrtoi(lpsz);
+                               for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz))
+                                       ;
+                       }
+                       ATLASSERT(nWidth >= 0);
+
+                       int nPrecision = 0;
+                       if (*lpsz == _T('.'))
+                       {
+                               // skip past '.' separator (width.precision)
+                               lpsz = ::CharNext(lpsz);
+
+                               // get precision and skip it
+                               if (*lpsz == _T('*'))
+                               {
+                                       nPrecision = va_arg(argList, int);
+                                       lpsz = ::CharNext(lpsz);
+                               }
+                               else
+                               {
+                                       nPrecision = _cstrtoi(lpsz);
+                                       for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz))
+                                               ;
+                               }
+                               ATLASSERT(nPrecision >= 0);
+                       }
+
+                       // should be on type modifier or specifier
+                       int nModifier = 0;
+                       if(lpsz[0] == _T('I') && lpsz[1] == _T('6') && lpsz[2] == _T('4'))
+                       {
+                               lpsz += 3;
+                               nModifier = FORCE_INT64;
+                       }
+                       else
+                       {
+                               switch (*lpsz)
+                               {
+                               // modifiers that affect size
+                               case _T('h'):
+                                       nModifier = FORCE_ANSI;
+                                       lpsz = ::CharNext(lpsz);
+                                       break;
+                               case _T('l'):
+                                       nModifier = FORCE_UNICODE;
+                                       lpsz = ::CharNext(lpsz);
+                                       break;
+
+                               // modifiers that do not affect size
+                               case _T('F'):
+                               case _T('N'):
+                               case _T('L'):
+                                       lpsz = ::CharNext(lpsz);
+                                       break;
+                               }
+                       }
+
+                       // now should be on specifier
+                       switch (*lpsz | nModifier)
+                       {
+                       // single characters
+                       case _T('c'):
+                       case _T('C'):
+                               nItemLen = 2;
+                               va_arg(argList, TCHAR);
+                               break;
+                       case _T('c') | FORCE_ANSI:
+                       case _T('C') | FORCE_ANSI:
+                               nItemLen = 2;
+                               va_arg(argList, char);
+                               break;
+                       case _T('c') | FORCE_UNICODE:
+                       case _T('C') | FORCE_UNICODE:
+                               nItemLen = 2;
+                               va_arg(argList, WCHAR);
+                               break;
+
+                       // strings
+                       case _T('s'):
+                       {
+                               LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
+                               if (pstrNextArg == NULL)
+                               {
+                                       nItemLen = 6;  // "(null)"
+                               }
+                               else
+                               {
+                                       nItemLen = lstrlen(pstrNextArg);
+                                       nItemLen = max(1, nItemLen);
+                               }
+                               break;
+                       }
+
+                       case _T('S'):
+                       {
+#ifndef _UNICODE
+                               LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
+                               if (pstrNextArg == NULL)
+                               {
+                                       nItemLen = 6;  // "(null)"
+                               }
+                               else
+                               {
+                                       nItemLen = (int)wcslen(pstrNextArg);
+                                       nItemLen = max(1, nItemLen);
+                               }
+#else // _UNICODE
+                               LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
+                               if (pstrNextArg == NULL)
+                               {
+                                       nItemLen = 6; // "(null)"
+                               }
+                               else
+                               {
+#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
+                                       nItemLen = ATL::lstrlenA(pstrNextArg);
+#else
+                                       nItemLen = lstrlenA(pstrNextArg);
+#endif
+                                       nItemLen = max(1, nItemLen);
+                               }
+#endif // _UNICODE
+                               break;
+                       }
+
+                       case _T('s') | FORCE_ANSI:
+                       case _T('S') | FORCE_ANSI:
+                       {
+                               LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
+                               if (pstrNextArg == NULL)
+                               {
+                                       nItemLen = 6; // "(null)"
+                               }
+                               else
+                               {
+#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
+                                       nItemLen = ATL::lstrlenA(pstrNextArg);
+#else
+                                       nItemLen = lstrlenA(pstrNextArg);
+#endif
+                                       nItemLen = max(1, nItemLen);
+                               }
+                               break;
+                       }
+
+                       case _T('s') | FORCE_UNICODE:
+                       case _T('S') | FORCE_UNICODE:
+                       {
+                               LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
+                               if (pstrNextArg == NULL)
+                               {
+                                       nItemLen = 6; // "(null)"
+                               }
+                               else
+                               {
+                                       nItemLen = (int)wcslen(pstrNextArg);
+                                       nItemLen = max(1, nItemLen);
+                               }
+                               break;
+                       }
+                       }
+
+                       // adjust nItemLen for strings
+                       if (nItemLen != 0)
+                       {
+                               nItemLen = max(nItemLen, nWidth);
+                               if (nPrecision != 0)
+                                       nItemLen = min(nItemLen, nPrecision);
+                       }
+                       else
+                       {
+                               switch (*lpsz)
+                               {
+                               // integers
+                               case _T('d'):
+                               case _T('i'):
+                               case _T('u'):
+                               case _T('x'):
+                               case _T('X'):
+                               case _T('o'):
+                                       if (nModifier & FORCE_INT64)
+                                               va_arg(argList, __int64);
+                                       else
+                                               va_arg(argList, int);
+                                       nItemLen = 32;
+                                       nItemLen = max(nItemLen, nWidth + nPrecision);
+                                       break;
+
+#ifndef _ATL_USE_CSTRING_FLOAT
+                               case _T('e'):
+                               case _T('E'):
+                               case _T('f'):
+                               case _T('g'):
+                               case _T('G'):
+                                       ATLASSERT(!"Floating point (%%e, %%E, %%f, %%g, and %%G) is not supported by the WTL::CString class.");
+#ifndef _DEBUG
+                                       ::OutputDebugString(_T("Floating point (%%e, %%f, %%g, and %%G) is not supported by the WTL::CString class."));
+#ifndef _WIN32_WCE
+                                       ::DebugBreak();
+#else // CE specific
+                                       DebugBreak();
+#endif // _WIN32_WCE
+#endif // !_DEBUG
+                                       break;
+#else // _ATL_USE_CSTRING_FLOAT
+                               case _T('e'):
+                               case _T('E'):
+                               case _T('g'):
+                               case _T('G'):
+                                       va_arg(argList, double);
+                                       nItemLen = 128;
+                                       nItemLen = max(nItemLen, nWidth + nPrecision);
+                                       break;
+                               case _T('f'):
+                                       {
+                                               double f = va_arg(argList, double);
+                                               // 312 == strlen("-1+(309 zeroes).")
+                                               // 309 zeroes == max precision of a double
+                                               // 6 == adjustment in case precision is not specified,
+                                               //   which means that the precision defaults to 6
+                                               int cchLen = max(nWidth, 312 + nPrecision + 6);
+                                               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+                                               LPTSTR pszTemp = buff.Allocate(cchLen);
+                                               if(pszTemp != NULL)
+                                               {
+                                                       SecureHelper::sprintf_x(pszTemp, cchLen, _T("%*.*f"), nWidth, nPrecision + 6, f);
+                                                       nItemLen = (int)_tcslen(pszTemp);
+                                               }
+                                               else
+                                               {
+                                                       nItemLen = cchLen;
+                                               }
+                                       }
+                                       break;
+#endif // _ATL_USE_CSTRING_FLOAT
+
+                               case _T('p'):
+                                       va_arg(argList, void*);
+                                       nItemLen = 32;
+                                       nItemLen = max(nItemLen, nWidth + nPrecision);
+                                       break;
+
+                               // no output
+                               case _T('n'):
+                                       va_arg(argList, int*);
+                                       break;
+
+                               default:
+                                       ATLASSERT(FALSE);  // unknown formatting option
+                               }
+                       }
+
+                       // adjust nMaxLen for output nItemLen
+                       nMaxLen += nItemLen;
+               }
+
+               if(GetBuffer(nMaxLen) == NULL)
+                       return FALSE;
+#ifndef _ATL_USE_CSTRING_FLOAT
+               int nRet = SecureHelper::wvsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave);
+#else // _ATL_USE_CSTRING_FLOAT
+               int nRet = SecureHelper::vsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave);
+#endif // _ATL_USE_CSTRING_FLOAT
+               nRet;   // ref
+               ATLASSERT(nRet <= GetAllocLength());
+               ReleaseBuffer();
+
+               va_end(argListSave);
+               return TRUE;
+       }
+
+       // formatting for localization (uses FormatMessage API)
+       // formatting (using FormatMessage style formatting)
+       BOOL __cdecl FormatMessage(LPCTSTR lpszFormat, ...)
+       {
+               // format message into temporary buffer lpszTemp
+               va_list argList;
+               va_start(argList, lpszFormat);
+               LPTSTR lpszTemp;
+               BOOL bRet = TRUE;
+
+               if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+                               lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL)
+                       bRet = FALSE;
+
+               // assign lpszTemp into the resulting string and free the temporary
+               *this = lpszTemp;
+               LocalFree(lpszTemp);
+               va_end(argList);
+               return bRet;
+       }
+
+       BOOL __cdecl FormatMessage(UINT nFormatID, ...)
+       {
+               // get format string from string table
+               CString strFormat;
+               BOOL bRetTmp = strFormat.LoadString(nFormatID);
+               bRetTmp;   // ref
+               ATLASSERT(bRetTmp != 0);
+
+               // format message into temporary buffer lpszTemp
+               va_list argList;
+               va_start(argList, nFormatID);
+               LPTSTR lpszTemp;
+               BOOL bRet = TRUE;
+
+               if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+                               strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL)
+                       bRet = FALSE;
+
+               // assign lpszTemp into the resulting string and free lpszTemp
+               *this = lpszTemp;
+               LocalFree(lpszTemp);
+               va_end(argList);
+               return bRet;
+       }
+
+       // Windows support
+       BOOL LoadString(UINT nID)   // load from string resource (255 chars max.)
+       {
+#ifdef _UNICODE
+               const int CHAR_FUDGE = 1;   // one TCHAR unused is good enough
+#else
+               const int CHAR_FUDGE = 2;   // two BYTES unused for case of DBC last char
+#endif
+
+               // try fixed buffer first (to avoid wasting space in the heap)
+               TCHAR szTemp[256];
+               int nCount =  sizeof(szTemp) / sizeof(szTemp[0]);
+               int nLen = _LoadString(nID, szTemp, nCount);
+               if (nCount - nLen > CHAR_FUDGE)
+               {
+                       *this = szTemp;
+                       return (nLen > 0);
+               }
+
+               // try buffer size of 512, then larger size until entire string is retrieved
+               int nSize = 256;
+               do
+               {
+                       nSize += 256;
+                       LPTSTR lpstr = GetBuffer(nSize - 1);
+                       if(lpstr == NULL)
+                       {
+                               nLen = 0;
+                               break;
+                       }
+                       nLen = _LoadString(nID, lpstr, nSize);
+               } while (nSize - nLen <= CHAR_FUDGE);
+               ReleaseBuffer();
+
+               return (nLen > 0);
+       }
+
+#ifndef _UNICODE
+       // ANSI <-> OEM support (convert string in place)
+       void AnsiToOem()
+       {
+               CopyBeforeWrite();
+               ::AnsiToOem(m_pchData, m_pchData);
+       }
+
+       void OemToAnsi()
+       {
+               CopyBeforeWrite();
+               ::OemToAnsi(m_pchData, m_pchData);
+       }
+#endif
+
+#ifndef _ATL_NO_COM
+       // OLE BSTR support (use for OLE automation)
+       BSTR AllocSysString() const
+       {
+#if defined(_UNICODE) || defined(OLE2ANSI)
+               BSTR bstr = ::SysAllocStringLen(m_pchData, GetData()->nDataLength);
+#else
+               int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData,
+                       GetData()->nDataLength, NULL, NULL);
+               BSTR bstr = ::SysAllocStringLen(NULL, nLen);
+               if(bstr != NULL)
+                       MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, bstr, nLen);
+#endif
+               return bstr;
+       }
+
+       BSTR SetSysString(BSTR* pbstr) const
+       {
+#if defined(_UNICODE) || defined(OLE2ANSI)
+               ::SysReAllocStringLen(pbstr, m_pchData, GetData()->nDataLength);
+#else
+               int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData,
+                       GetData()->nDataLength, NULL, NULL);
+               if(::SysReAllocStringLen(pbstr, NULL, nLen))
+                       MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, *pbstr, nLen);
+#endif
+               ATLASSERT(*pbstr != NULL);
+               return *pbstr;
+       }
+#endif // !_ATL_NO_COM
+
+       // Access to string implementation buffer as "C" character array
+       LPTSTR GetBuffer(int nMinBufLength)
+       {
+               ATLASSERT(nMinBufLength >= 0);
+
+               if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
+               {
+                       // we have to grow the buffer
+                       CStringData* pOldData = GetData();
+                       int nOldLen = GetData()->nDataLength;   // AllocBuffer will tromp it
+                       if (nMinBufLength < nOldLen)
+                               nMinBufLength = nOldLen;
+
+                       if(!AllocBuffer(nMinBufLength))
+                               return NULL;
+
+                       SecureHelper::memcpy_x(m_pchData, (nMinBufLength + 1) * sizeof(TCHAR), pOldData->data(), (nOldLen + 1) * sizeof(TCHAR));
+                       GetData()->nDataLength = nOldLen;
+                       CString::Release(pOldData);
+               }
+               ATLASSERT(GetData()->nRefs <= 1);
+
+               // return a pointer to the character storage for this string
+               ATLASSERT(m_pchData != NULL);
+               return m_pchData;
+       }
+
+       void ReleaseBuffer(int nNewLength = -1)
+       {
+               CopyBeforeWrite();   // just in case GetBuffer was not called
+
+               if (nNewLength == -1)
+                       nNewLength = lstrlen(m_pchData);   // zero terminated
+
+               ATLASSERT(nNewLength <= GetData()->nAllocLength);
+               GetData()->nDataLength = nNewLength;
+               m_pchData[nNewLength] = _T('\0');
+       }
+
+       LPTSTR GetBufferSetLength(int nNewLength)
+       {
+               ATLASSERT(nNewLength >= 0);
+
+               if(GetBuffer(nNewLength) == NULL)
+                       return NULL;
+
+               GetData()->nDataLength = nNewLength;
+               m_pchData[nNewLength] = _T('\0');
+               return m_pchData;
+       }
+
+       void FreeExtra()
+       {
+               ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
+               if (GetData()->nDataLength != GetData()->nAllocLength)
+               {
+                       CStringData* pOldData = GetData();
+                       if(AllocBuffer(GetData()->nDataLength))
+                       {
+                               SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pOldData->data(), pOldData->nDataLength * sizeof(TCHAR));
+                               ATLASSERT(m_pchData[GetData()->nDataLength] == _T('\0'));
+                               CString::Release(pOldData);
+                       }
+               }
+               ATLASSERT(GetData() != NULL);
+       }
+
+       // Use LockBuffer/UnlockBuffer to turn refcounting off
+       LPTSTR LockBuffer()
+       {
+               LPTSTR lpsz = GetBuffer(0);
+               if(lpsz != NULL)
+                       GetData()->nRefs = -1;
+               return lpsz;
+       }
+
+       void UnlockBuffer()
+       {
+               ATLASSERT(GetData()->nRefs == -1);
+               if (GetData() != _atltmpDataNil)
+                       GetData()->nRefs = 1;
+       }
+
+// Implementation
+public:
+       ~CString()   //  free any attached data
+       {
+               if (GetData() != _atltmpDataNil)
+               {
+                       if (InterlockedDecrement(&GetData()->nRefs) <= 0)
+                               delete[] (BYTE*)GetData();
+               }
+       }
+
+       int GetAllocLength() const
+       {
+               return GetData()->nAllocLength;
+       }
+
+       static BOOL __stdcall _IsValidString(LPCTSTR lpsz, int /*nLength*/ = -1)
+       {
+               return (lpsz != NULL) ? TRUE : FALSE;
+       }
+
+protected:
+       LPTSTR m_pchData;   // pointer to ref counted string data
+
+       // implementation helpers
+       CStringData* GetData() const
+       {
+               ATLASSERT(m_pchData != NULL);
+               return ((CStringData*)m_pchData) - 1;
+       }
+
+       void Init()
+       {
+               m_pchData = _GetEmptyString().m_pchData;
+       }
+
+       BOOL AllocCopy(CString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const
+       {
+               // will clone the data attached to this string
+               // allocating 'nExtraLen' characters
+               // Places results in uninitialized string 'dest'
+               // Will copy the part or all of original data to start of new string
+
+               BOOL bRet = FALSE;
+               int nNewLen = nCopyLen + nExtraLen;
+               if (nNewLen == 0)
+               {
+                       dest.Init();
+                       bRet = TRUE;
+               }
+               else if(nNewLen >= nCopyLen)
+               {
+                       if(dest.AllocBuffer(nNewLen))
+                       {
+                               SecureHelper::memcpy_x(dest.m_pchData, (nNewLen + 1) * sizeof(TCHAR), m_pchData + nCopyIndex, nCopyLen * sizeof(TCHAR));
+                               bRet = TRUE;
+                       }
+               }
+
+               return bRet;
+       }
+
+       // always allocate one extra character for '\0' termination
+       // assumes [optimistically] that data length will equal allocation length
+       BOOL AllocBuffer(int nLen)
+       {
+               ATLASSERT(nLen >= 0);
+               ATLASSERT(nLen <= INT_MAX - 1);   // max size (enough room for 1 extra)
+
+               if (nLen == 0)
+               {
+                       Init();
+               }
+               else
+               {
+                       CStringData* pData = NULL;
+                       ATLTRY(pData = (CStringData*)new BYTE[sizeof(CStringData) + (nLen + 1) * sizeof(TCHAR)]);
+                       if(pData == NULL)
+                               return FALSE;
+
+                       pData->nRefs = 1;
+                       pData->data()[nLen] = _T('\0');
+                       pData->nDataLength = nLen;
+                       pData->nAllocLength = nLen;
+                       m_pchData = pData->data();
+               }
+
+               return TRUE;
+       }
+
+       // Assignment operators
+       //  All assign a new value to the string
+       //      (a) first see if the buffer is big enough
+       //      (b) if enough room, copy on top of old buffer, set size and type
+       //      (c) otherwise free old string data, and create a new one
+       //
+       //  All routines return the new string (but as a 'const CString&' so that
+       //      assigning it again will cause a copy, eg: s1 = s2 = "hi there".
+       //
+       void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
+       {
+               if(AllocBeforeWrite(nSrcLen))
+               {
+                       SecureHelper::memcpy_x(m_pchData, (nSrcLen + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR));
+                       GetData()->nDataLength = nSrcLen;
+                       m_pchData[nSrcLen] = _T('\0');
+               }
+       }
+
+       // Concatenation
+       // NOTE: "operator +" is done as friend functions for simplicity
+       //      There are three variants:
+       //          CString + CString
+       // and for ? = TCHAR, LPCTSTR
+       //          CString + ?
+       //          ? + CString
+       BOOL ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data)
+       {
+               // -- master concatenation routine
+               // Concatenate two sources
+               // -- assume that 'this' is a new CString object
+
+               BOOL bRet = TRUE;
+               int nNewLen = nSrc1Len + nSrc2Len;
+               if(nNewLen < nSrc1Len || nNewLen < nSrc2Len)
+               {
+                       bRet = FALSE;
+               }
+               else if(nNewLen != 0)
+               {
+                       bRet = AllocBuffer(nNewLen);
+                       if (bRet)
+                       {
+                               SecureHelper::memcpy_x(m_pchData, (nNewLen + 1) * sizeof(TCHAR), lpszSrc1Data, nSrc1Len * sizeof(TCHAR));
+                               SecureHelper::memcpy_x(m_pchData + nSrc1Len, (nNewLen + 1 - nSrc1Len) * sizeof(TCHAR), lpszSrc2Data, nSrc2Len * sizeof(TCHAR));
+                       }
+               }
+               return bRet;
+       }
+
+       void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
+       {
+               //  -- the main routine for += operators
+
+               // concatenating an empty string is a no-op!
+               if (nSrcLen == 0)
+                       return;
+
+               // if the buffer is too small, or we have a width mis-match, just
+               //   allocate a new buffer (slow but sure)
+               if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
+               {
+                       // we have to grow the buffer, use the ConcatCopy routine
+                       CStringData* pOldData = GetData();
+                       if (ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData))
+                       {
+                               ATLASSERT(pOldData != NULL);
+                               CString::Release(pOldData);
+                       }
+               }
+               else
+               {
+                       // fast concatenation when buffer big enough
+                       SecureHelper::memcpy_x(m_pchData + GetData()->nDataLength, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR));
+                       GetData()->nDataLength += nSrcLen;
+                       ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
+                       m_pchData[GetData()->nDataLength] = _T('\0');
+               }
+       }
+
+       void CopyBeforeWrite()
+       {
+               if (GetData()->nRefs > 1)
+               {
+                       CStringData* pData = GetData();
+                       Release();
+                       if(AllocBuffer(pData->nDataLength))
+                               SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pData->data(), (pData->nDataLength + 1) * sizeof(TCHAR));
+               }
+               ATLASSERT(GetData()->nRefs <= 1);
+       }
+
+       BOOL AllocBeforeWrite(int nLen)
+       {
+               BOOL bRet = TRUE;
+               if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
+               {
+                       Release();
+                       bRet = AllocBuffer(nLen);
+               }
+               ATLASSERT(GetData()->nRefs <= 1);
+               return bRet;
+       }
+
+       void Release()
+       {
+               if (GetData() != _atltmpDataNil)
+               {
+                       ATLASSERT(GetData()->nRefs != 0);
+                       if (InterlockedDecrement(&GetData()->nRefs) <= 0)
+                               delete[] (BYTE*)GetData();
+                       Init();
+               }
+       }
+
+       static void PASCAL Release(CStringData* pData)
+       {
+               if (pData != _atltmpDataNil)
+               {
+                       ATLASSERT(pData->nRefs != 0);
+                       if (InterlockedDecrement(&pData->nRefs) <= 0)
+                               delete[] (BYTE*)pData;
+               }
+       }
+
+       static int PASCAL SafeStrlen(LPCTSTR lpsz)
+       {
+               return (lpsz == NULL) ? 0 : lstrlen(lpsz);
+       }
+
+       static int __stdcall _LoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf)
+       {
+#ifdef _DEBUG
+               // LoadString without annoying warning from the Debug kernel if the
+               //  segment containing the string is not present
+               if (::FindResource(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE((nID >> 4) + 1), RT_STRING) == NULL)
+               {
+                       lpszBuf[0] = _T('\0');
+                       return 0;   // not found
+               }
+#endif // _DEBUG
+
+               int nLen = ::LoadString(ModuleHelper::GetResourceInstance(), nID, lpszBuf, nMaxBuf);
+               if (nLen == 0)
+                       lpszBuf[0] = _T('\0');
+
+               return nLen;
+       }
+
+       static const CString& __stdcall _GetEmptyString()
+       {
+               return *(CString*)&_atltmpPchNil;
+       }
+
+// CString conversion helpers
+       static int __cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count)
+       {
+               if (count == 0 && mbstr != NULL)
+                       return 0;
+
+               int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1, mbstr, (int)count, NULL, NULL);
+               ATLASSERT(mbstr == NULL || result <= (int)count);
+               if (result > 0)
+                       mbstr[result - 1] = 0;
+               return result;
+       }
+
+       static int __cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count)
+       {
+               if (count == 0 && wcstr != NULL)
+                       return 0;
+
+               int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1, wcstr, (int)count);
+               ATLASSERT(wcstr == NULL || result <= (int)count);
+               if (result > 0)
+                       wcstr[result - 1] = 0;
+               return result;
+       }
+
+// Helpers to avoid CRT startup code
+#ifdef _ATL_MIN_CRT
+       static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch)
+       {
+               // strchr for '\0' should succeed
+               while (*p != 0)
+               {
+                       if (*p == ch)
+                               break;
+                       p = ::CharNext(p);
+               }
+               return (*p == ch) ? p : NULL;
+       }
+
+       static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch)
+       {
+               const TCHAR* lpsz = NULL;
+               while (*p != 0)
+               {
+                       if (*p == ch)
+                               lpsz = p;
+                       p = ::CharNext(p);
+               }
+               return lpsz;
+       }
+
+       static TCHAR* _cstrrev(TCHAR* pStr)
+       {
+               // optimize NULL, zero-length, and single-char case
+               if ((pStr == NULL) || (pStr[0] == _T('\0')) || (pStr[1] == _T('\0')))
+                       return pStr;
+
+               TCHAR* p = pStr;
+
+               while (*p != 0) 
+               {
+                       TCHAR* pNext = ::CharNext(p);
+                       if(pNext > p + 1)
+                       {
+                               char p1 = *(char*)p;
+                               *(char*)p = *(char*)(p + 1);
+                               *(char*)(p + 1) = p1;
+                       }
+                       p = pNext;
+               }
+
+               p--;
+               TCHAR* q = pStr;
+
+               while (q < p)
+               {
+                       TCHAR t = *q;
+                       *q = *p;
+                       *p = t;
+                       q++;
+                       p--;
+               }
+               return pStr;
+       }
+
+       static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet)
+       {
+               int nLen = lstrlen(pCharSet);
+               if (nLen == 0)
+                       return (TCHAR*)pStr;
+
+               const TCHAR* pRet = NULL;
+               const TCHAR* pCur = pStr;
+               while((pCur = _cstrchr(pCur, *pCharSet)) != NULL)
+               {
+                       if(memcmp(pCur, pCharSet, nLen * sizeof(TCHAR)) == 0)
+                       {
+                               pRet = pCur;
+                               break;
+                       }
+                       pCur = ::CharNext(pCur);
+               }
+               return pRet;
+       }
+
+       static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet)
+       {
+               int nRet = 0;
+               const TCHAR* p = pStr;
+               while (*p != 0)
+               {
+                       const TCHAR* pNext = ::CharNext(p);
+                       if(pNext > p + 1)
+                       {
+                               if(_cstrchr_db(pCharSet, *p, *(p + 1)) == NULL)
+                                       break;
+                               nRet += 2;
+                       }
+                       else
+                       {
+                               if(_cstrchr(pCharSet, *p) == NULL)
+                                       break;
+                               nRet++;
+                       }
+                       p = pNext;
+               }
+               return nRet;
+       }
+
+       static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet)
+       {
+               int nRet = 0;
+               TCHAR* p = (TCHAR*)pStr;
+               while (*p != 0)
+               {
+                       TCHAR* pNext = ::CharNext(p);
+                       if(pNext > p + 1)
+                       {
+                               if(_cstrchr_db(pCharSet, *p, *(p + 1)) != NULL)
+                                       break;
+                               nRet += 2;
+                       }
+                       else
+                       {
+                               if(_cstrchr(pCharSet, *p) != NULL)
+                                       break;
+                               nRet++;
+                       }
+                       p = pNext;
+               }
+               return nRet;
+       }
+
+       static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet)
+       {
+               int n = _cstrcspn(p, lpszCharSet);
+               return (p[n] != 0) ? &p[n] : NULL;
+       }
+
+       static int _cstrisdigit(TCHAR ch)
+       {
+               WORD type;
+               GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
+               return (type & C1_DIGIT) == C1_DIGIT;
+       }
+
+       static int _cstrisspace(TCHAR ch)
+       {
+               WORD type;
+               GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
+               return (type & C1_SPACE) == C1_SPACE;
+       }
+
+       static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther)
+       {
+               return lstrcmp(pstrOne, pstrOther);
+       }
+
+       static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther)
+       {
+               return lstrcmpi(pstrOne, pstrOther);
+       }
+
+       static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther)
+       {
+               int nRet = CompareString(GetThreadLocale(), 0, pstrOne, -1, pstrOther, -1);
+               ATLASSERT(nRet != 0);
+               return nRet - 2;   // convert to strcmp convention
+       }
+
+       static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther)
+       {
+               int nRet = CompareString(GetThreadLocale(), NORM_IGNORECASE, pstrOne, -1, pstrOther, -1);
+               ATLASSERT(nRet != 0);
+               return nRet - 2;   // convert to strcmp convention
+       }
+
+       static int _cstrtoi(const TCHAR* nptr)
+       {
+               int c;       // current char
+               int total;   // current total
+               int sign;    // if '-', then negative, otherwise positive
+
+               while (_cstrisspace(*nptr))
+                       ++nptr;
+
+               c = (int)(_TUCHAR)*nptr++;
+               sign = c;   // save sign indication
+               if (c == _T('-') || c == _T('+'))
+                       c = (int)(_TUCHAR)*nptr++;   // skip sign
+
+               total = 0;
+
+               while (_cstrisdigit((TCHAR)c))
+               {
+                       total = 10 * total + (c - '0');   // accumulate digit
+                       c = (int)(_TUCHAR)*nptr++;        // get next char
+               }
+
+               if (sign == '-')
+                       return -total;
+               else
+                       return total;   // return result, negated if necessary
+       }
+#else // !_ATL_MIN_CRT
+       static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch)
+       {
+               return _tcschr(p, ch);
+       }
+
+       static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch)
+       {
+               return _tcsrchr(p, ch);
+       }
+
+       static TCHAR* _cstrrev(TCHAR* pStr)
+       {
+               return _tcsrev(pStr);
+       }
+
+       static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet)
+       {
+               return _tcsstr(pStr, pCharSet);
+       }
+
+       static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet)
+       {
+               return (int)_tcsspn(pStr, pCharSet);
+       }
+
+       static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet)
+       {
+               return (int)_tcscspn(pStr, pCharSet);
+       }
+
+       static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet)
+       {
+               return _tcspbrk(p, lpszCharSet);
+       }
+
+       static int _cstrisdigit(TCHAR ch)
+       {
+               return _istdigit(ch);
+       }
+
+       static int _cstrisspace(TCHAR ch)
+       {
+               return _istspace((_TUCHAR)ch);
+       }
+
+       static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther)
+       {
+               return _tcscmp(pstrOne, pstrOther);
+       }
+
+       static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther)
+       {
+               return _tcsicmp(pstrOne, pstrOther);
+       }
+
+#ifndef _WIN32_WCE
+       static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther)
+       {
+               return _tcscoll(pstrOne, pstrOther);
+       }
+
+       static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther)
+       {
+               return _tcsicoll(pstrOne, pstrOther);
+       }
+#endif // !_WIN32_WCE
+
+       static int _cstrtoi(const TCHAR* nptr)
+       {
+               return _ttoi(nptr);
+       }
+#endif // !_ATL_MIN_CRT
+
+       static const TCHAR* _cstrchr_db(const TCHAR* p, TCHAR ch1, TCHAR ch2)
+       {
+               const TCHAR* lpsz = NULL;
+               while (*p != 0)
+               {
+                       if (*p == ch1 && *(p + 1) == ch2)
+                       {
+                               lpsz = p;
+                               break;
+                       }
+                       p = ::CharNext(p);
+               }
+               return lpsz;
+       }
+};
+
+
+// Compare helpers
+
+inline bool __stdcall operator ==(const CString& s1, const CString& s2)
+{ return s1.Compare(s2) == 0; }
+
+inline bool __stdcall operator ==(const CString& s1, LPCTSTR s2)
+{ return s1.Compare(s2) == 0; }
+
+inline bool __stdcall operator ==(LPCTSTR s1, const CString& s2)
+{ return s2.Compare(s1) == 0; }
+
+inline bool __stdcall operator !=(const CString& s1, const CString& s2)
+{ return s1.Compare(s2) != 0; }
+
+inline bool __stdcall operator !=(const CString& s1, LPCTSTR s2)
+{ return s1.Compare(s2) != 0; }
+
+inline bool __stdcall operator !=(LPCTSTR s1, const CString& s2)
+{ return s2.Compare(s1) != 0; }
+
+inline bool __stdcall operator <(const CString& s1, const CString& s2)
+{ return s1.Compare(s2) < 0; }
+
+inline bool __stdcall operator <(const CString& s1, LPCTSTR s2)
+{ return s1.Compare(s2) < 0; }
+
+inline bool __stdcall operator <(LPCTSTR s1, const CString& s2)
+{ return s2.Compare(s1) > 0; }
+
+inline bool __stdcall operator >(const CString& s1, const CString& s2)
+{ return s1.Compare(s2) > 0; }
+
+inline bool __stdcall operator >(const CString& s1, LPCTSTR s2)
+{ return s1.Compare(s2) > 0; }
+
+inline bool __stdcall operator >(LPCTSTR s1, const CString& s2)
+{ return s2.Compare(s1) < 0; }
+
+inline bool __stdcall operator <=(const CString& s1, const CString& s2)
+{ return s1.Compare(s2) <= 0; }
+
+inline bool __stdcall operator <=(const CString& s1, LPCTSTR s2)
+{ return s1.Compare(s2) <= 0; }
+
+inline bool __stdcall operator <=(LPCTSTR s1, const CString& s2)
+{ return s2.Compare(s1) >= 0; }
+
+inline bool __stdcall operator >=(const CString& s1, const CString& s2)
+{ return s1.Compare(s2) >= 0; }
+
+inline bool __stdcall operator >=(const CString& s1, LPCTSTR s2)
+{ return s1.Compare(s2) >= 0; }
+
+inline bool __stdcall operator >=(LPCTSTR s1, const CString& s2)
+{ return s2.Compare(s1) <= 0; }
+
+
+// CString "operator +" functions
+
+inline CString __stdcall operator +(const CString& string1, const CString& string2)
+{
+       CString s;
+       s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, string2.GetData()->nDataLength, string2.m_pchData);
+       return s;
+}
+
+inline CString __stdcall operator +(const CString& string, TCHAR ch)
+{
+       CString s;
+       s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, 1, &ch);
+       return s;
+}
+
+inline CString __stdcall operator +(TCHAR ch, const CString& string)
+{
+       CString s;
+       s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
+       return s;
+}
+
+#ifdef _UNICODE
+inline CString __stdcall operator +(const CString& string, char ch)
+{
+       return string + (TCHAR)ch;
+}
+
+inline CString __stdcall operator +(char ch, const CString& string)
+{
+       return (TCHAR)ch + string;
+}
+#endif // _UNICODE
+
+inline CString __stdcall operator +(const CString& string, LPCTSTR lpsz)
+{
+       ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz));
+       CString s;
+       s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, CString::SafeStrlen(lpsz), lpsz);
+       return s;
+}
+
+inline CString __stdcall operator +(LPCTSTR lpsz, const CString& string)
+{
+       ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz));
+       CString s;
+       s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength, string.m_pchData);
+       return s;
+}
+
+#endif // !_WTL_NO_CSTRING
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CRecentDocumentList - MRU List Support
+
+#ifndef _WIN32_WCE
+
+#ifndef _WTL_MRUEMPTY_TEXT
+  #define _WTL_MRUEMPTY_TEXT   _T("(empty)")
+#endif
+
+// forward declaration
+inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen);
+
+template <class T, int t_cchItemLen = MAX_PATH, int t_nFirstID = ID_FILE_MRU_FIRST, int t_nLastID = ID_FILE_MRU_LAST>
+class CRecentDocumentListBase
+{
+public:
+// Declarations
+       struct _DocEntry
+       {
+               TCHAR szDocName[t_cchItemLen];
+               bool operator ==(const _DocEntry& de) const
+               { return (lstrcmpi(szDocName, de.szDocName) == 0); }
+       };
+
+       enum
+       {
+               m_nMaxEntries_Min = 2,
+               m_nMaxEntries_Max = t_nLastID - t_nFirstID + 1,
+               m_cchMaxItemLen_Min = 6,
+               m_cchMaxItemLen_Max = t_cchItemLen,
+               m_cchItemNameLen = 11
+       };
+
+// Data members
+       ATL::CSimpleArray<_DocEntry> m_arrDocs;
+       int m_nMaxEntries;   // default is 4
+       HMENU m_hMenu;
+
+       TCHAR m_szNoEntries[t_cchItemLen];
+
+       int m_cchMaxItemLen;
+
+// Constructor
+       CRecentDocumentListBase() : m_hMenu(NULL), m_nMaxEntries(4), m_cchMaxItemLen(-1)
+       {
+               // These ASSERTs verify values of the template arguments
+               ATLASSERT(t_cchItemLen > m_cchMaxItemLen_Min);
+               ATLASSERT(m_nMaxEntries_Max > m_nMaxEntries_Min);
+       }
+
+// Attributes
+       HMENU GetMenuHandle() const
+       {
+               return m_hMenu;
+       }
+
+       void SetMenuHandle(HMENU hMenu)
+       {
+               ATLASSERT(hMenu == NULL || ::IsMenu(hMenu));
+               m_hMenu = hMenu;
+               if(m_hMenu == NULL || (::GetMenuString(m_hMenu, t_nFirstID, m_szNoEntries, t_cchItemLen, MF_BYCOMMAND) == 0))
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT;   // avoid level 4 warning
+                       SecureHelper::strncpy_x(m_szNoEntries, _countof(m_szNoEntries), pT->GetMRUEmptyText(), _TRUNCATE);
+               }
+       }
+
+       int GetMaxEntries() const
+       {
+               return m_nMaxEntries;
+       }
+
+       void SetMaxEntries(int nMaxEntries)
+       {
+               ATLASSERT(nMaxEntries >= m_nMaxEntries_Min && nMaxEntries <= m_nMaxEntries_Max);
+               if(nMaxEntries < m_nMaxEntries_Min)
+                       nMaxEntries = m_nMaxEntries_Min;
+               else if(nMaxEntries > m_nMaxEntries_Max)
+                       nMaxEntries = m_nMaxEntries_Max;
+               m_nMaxEntries = nMaxEntries;
+       }
+
+       int GetMaxItemLength() const
+       {
+               return m_cchMaxItemLen;
+       }
+
+       void SetMaxItemLength(int cchMaxLen)
+       {
+               ATLASSERT((cchMaxLen >= m_cchMaxItemLen_Min && cchMaxLen <= m_cchMaxItemLen_Max) || cchMaxLen == -1);
+               if(cchMaxLen != -1)
+               {
+                       if(cchMaxLen < m_cchMaxItemLen_Min)
+                               cchMaxLen = m_cchMaxItemLen_Min;
+                       else if(cchMaxLen > m_cchMaxItemLen_Max)
+                               cchMaxLen = m_cchMaxItemLen_Max;
+               }
+               m_cchMaxItemLen = cchMaxLen;
+               T* pT = static_cast<T*>(this);
+               pT->UpdateMenu();
+       }
+
+// Operations
+       BOOL AddToList(LPCTSTR lpstrDocName)
+       {
+               _DocEntry de;
+               errno_t nRet = SecureHelper::strncpy_x(de.szDocName, _countof(de.szDocName), lpstrDocName, _TRUNCATE);
+               if(nRet != 0 && nRet != STRUNCATE)
+                       return FALSE;
+
+               for(int i = 0; i < m_arrDocs.GetSize(); i++)
+               {
+                       if(lstrcmpi(m_arrDocs[i].szDocName, lpstrDocName) == 0)
+                       {
+                               m_arrDocs.RemoveAt(i);
+                               break;
+                       }
+               }
+
+               if(m_arrDocs.GetSize() == m_nMaxEntries)
+                       m_arrDocs.RemoveAt(0);
+
+               BOOL bRet = m_arrDocs.Add(de);
+               if(bRet)
+               {
+                       T* pT = static_cast<T*>(this);
+                       bRet = pT->UpdateMenu();
+               }
+               return bRet;
+       }
+
+       // This function is deprecated because it is not safe. 
+       // Use the version below that accepts the buffer length.
+#if (_MSC_VER >= 1300)
+       __declspec(deprecated)
+#endif
+       BOOL GetFromList(int /*nItemID*/, LPTSTR /*lpstrDocName*/)
+       {
+               ATLASSERT(FALSE);
+               return FALSE;
+       }
+
+       BOOL GetFromList(int nItemID, LPTSTR lpstrDocName, int cchLength)
+       {
+               int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1;
+               if(nIndex < 0 || nIndex >= m_arrDocs.GetSize())
+                       return FALSE;
+               if(lstrlen(m_arrDocs[nIndex].szDocName) >= cchLength)
+                       return FALSE;
+               SecureHelper::strcpy_x(lpstrDocName, cchLength, m_arrDocs[nIndex].szDocName);
+
+               return TRUE;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       BOOL GetFromList(int nItemID, _CSTRING_NS::CString& strDocName)
+       {
+               int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1;
+               if(nIndex < 0 || nIndex >= m_arrDocs.GetSize())
+                       return FALSE;
+               strDocName = m_arrDocs[nIndex].szDocName;
+               return TRUE;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       BOOL RemoveFromList(int nItemID)
+       {
+               int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1;
+               BOOL bRet = m_arrDocs.RemoveAt(nIndex);
+               if(bRet)
+               {
+                       T* pT = static_cast<T*>(this);
+                       bRet = pT->UpdateMenu();
+               }
+               return bRet;
+       }
+
+       BOOL MoveToTop(int nItemID)
+       {
+               int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1;
+               if(nIndex < 0 || nIndex >= m_arrDocs.GetSize())
+                       return FALSE;
+               _DocEntry de;
+               de = m_arrDocs[nIndex];
+               m_arrDocs.RemoveAt(nIndex);
+               BOOL bRet = m_arrDocs.Add(de);
+               if(bRet)
+               {
+                       T* pT = static_cast<T*>(this);
+                       bRet = pT->UpdateMenu();
+               }
+               return bRet;
+       }
+
+       BOOL ReadFromRegistry(LPCTSTR lpstrRegKey)
+       {
+               T* pT = static_cast<T*>(this);
+               ATL::CRegKey rkParent;
+               ATL::CRegKey rk;
+
+               LONG lRet = rkParent.Open(HKEY_CURRENT_USER, lpstrRegKey);
+               if(lRet != ERROR_SUCCESS)
+                       return FALSE;
+               lRet = rk.Open(rkParent, pT->GetRegKeyName());
+               if(lRet != ERROR_SUCCESS)
+                       return FALSE;
+
+               DWORD dwRet = 0;
+#if (_ATL_VER >= 0x0700)
+               lRet = rk.QueryDWORDValue(pT->GetRegCountName(), dwRet);
+#else
+               lRet = rk.QueryValue(dwRet, pT->GetRegCountName());
+#endif
+               if(lRet != ERROR_SUCCESS)
+                       return FALSE;
+               SetMaxEntries(dwRet);
+
+               m_arrDocs.RemoveAll();
+
+               TCHAR szRetString[t_cchItemLen] = { 0 };
+               _DocEntry de;
+
+               for(int nItem = m_nMaxEntries; nItem > 0; nItem--)
+               {
+                       TCHAR szBuff[m_cchItemNameLen] = { 0 };
+                       SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem);
+#if (_ATL_VER >= 0x0700)
+                       ULONG ulCount = t_cchItemLen;
+                       lRet = rk.QueryStringValue(szBuff, szRetString, &ulCount);
+#else
+                       DWORD dwCount = t_cchItemLen * sizeof(TCHAR);
+                       lRet = rk.QueryValue(szRetString, szBuff, &dwCount);
+#endif
+                       if(lRet == ERROR_SUCCESS)
+                       {
+                               SecureHelper::strcpy_x(de.szDocName, _countof(de.szDocName), szRetString);
+                               m_arrDocs.Add(de);
+                       }
+               }
+
+               rk.Close();
+               rkParent.Close();
+
+               return pT->UpdateMenu();
+       }
+
+       BOOL WriteToRegistry(LPCTSTR lpstrRegKey)
+       {
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+               ATL::CRegKey rkParent;
+               ATL::CRegKey rk;
+
+               LONG lRet = rkParent.Create(HKEY_CURRENT_USER, lpstrRegKey);
+               if(lRet != ERROR_SUCCESS)
+                       return FALSE;
+               lRet = rk.Create(rkParent, pT->GetRegKeyName());
+               if(lRet != ERROR_SUCCESS)
+                       return FALSE;
+
+#if (_ATL_VER >= 0x0700)
+               lRet = rk.SetDWORDValue(pT->GetRegCountName(), m_nMaxEntries);
+#else
+               lRet = rk.SetValue(m_nMaxEntries, pT->GetRegCountName());
+#endif
+               ATLASSERT(lRet == ERROR_SUCCESS);
+
+               // set new values
+               int nItem;
+               for(nItem = m_arrDocs.GetSize(); nItem > 0; nItem--)
+               {
+                       TCHAR szBuff[m_cchItemNameLen] = { 0 };
+                       SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem);
+                       TCHAR szDocName[t_cchItemLen] = { 0 };
+                       GetFromList(t_nFirstID + nItem - 1, szDocName, t_cchItemLen);
+#if (_ATL_VER >= 0x0700)
+                       lRet = rk.SetStringValue(szBuff, szDocName);
+#else
+                       lRet = rk.SetValue(szDocName, szBuff);
+#endif
+                       ATLASSERT(lRet == ERROR_SUCCESS);
+               }
+
+               // delete unused keys
+               for(nItem = m_arrDocs.GetSize() + 1; nItem < m_nMaxEntries_Max; nItem++)
+               {
+                       TCHAR szBuff[m_cchItemNameLen] = { 0 };
+                       SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem);
+                       rk.DeleteValue(szBuff);
+               }
+
+               rk.Close();
+               rkParent.Close();
+
+               return TRUE;
+       }
+
+// Implementation
+       BOOL UpdateMenu()
+       {
+               if(m_hMenu == NULL)
+                       return FALSE;
+               ATLASSERT(::IsMenu(m_hMenu));
+
+               int nItems = ::GetMenuItemCount(m_hMenu);
+               int nInsertPoint;
+               for(nInsertPoint = 0; nInsertPoint < nItems; nInsertPoint++)
+               {
+                       CMenuItemInfo mi;
+                       mi.fMask = MIIM_ID;
+                       ::GetMenuItemInfo(m_hMenu, nInsertPoint, TRUE, &mi);
+                       if (mi.wID == t_nFirstID)
+                               break;
+               }
+               ATLASSERT(nInsertPoint < nItems && "You need a menu item with an ID = t_nFirstID");
+
+               int nItem;
+               for(nItem = t_nFirstID; nItem < t_nFirstID + m_nMaxEntries; nItem++)
+               {
+                       // keep the first one as an insertion point
+                       if (nItem != t_nFirstID)
+                               ::DeleteMenu(m_hMenu, nItem, MF_BYCOMMAND);
+               }
+
+               TCHAR szItemText[t_cchItemLen + 6] = { 0 };   // add space for &, 2 digits, and a space
+               int nSize = m_arrDocs.GetSize();
+               nItem = 0;
+               if(nSize > 0)
+               {
+                       for(nItem = 0; nItem < nSize; nItem++)
+                       {
+                               if(m_cchMaxItemLen == -1)
+                               {
+                                       SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, m_arrDocs[nSize - 1 - nItem].szDocName);
+                               }
+                               else
+                               {
+                                       TCHAR szBuff[t_cchItemLen] = { 0 };
+                                       T* pT = static_cast<T*>(this);
+                                       pT;   // avoid level 4 warning
+                                       bool bRet = pT->CompactDocumentName(szBuff, m_arrDocs[nSize - 1 - nItem].szDocName, m_cchMaxItemLen);
+                                       bRet;   // avoid level 4 warning
+                                       ATLASSERT(bRet);
+                                       SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, szBuff);
+                               }
+                               ::InsertMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION | MF_STRING, t_nFirstID + nItem, szItemText);
+                       }
+               }
+               else    // empty
+               {
+                       ::InsertMenu(m_hMenu, nInsertPoint, MF_BYPOSITION | MF_STRING, t_nFirstID, m_szNoEntries);
+                       ::EnableMenuItem(m_hMenu, t_nFirstID, MF_GRAYED);
+                       nItem++;
+               }
+               ::DeleteMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION);
+
+               return TRUE;
+       }
+
+// Overrideables
+       // override to provide a different method of compacting document names
+       static bool CompactDocumentName(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen)
+       {
+               return AtlCompactPath(lpstrOut, lpstrIn, cchLen);
+       }
+
+       static LPCTSTR GetRegKeyName()
+       {
+               return _T("Recent Document List");
+       }
+
+       static LPCTSTR GetRegCountName()
+       {
+               return _T("DocumentCount");
+       }
+
+       static LPCTSTR GetRegItemName()
+       {
+               // Note: This string is a format string used with wsprintf().
+               // Resulting formatted string must be m_cchItemNameLen or less 
+               // characters long, including the terminating null character.
+               return _T("Document%i");
+       }
+
+       static LPCTSTR GetMRUEmptyText()
+       {
+               return _WTL_MRUEMPTY_TEXT;
+       }
+};
+
+class CRecentDocumentList : public CRecentDocumentListBase<CRecentDocumentList>
+{
+public:
+// nothing here
+};
+
+#endif // _WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CFindFile - file search helper class
+
+class CFindFile
+{
+public:
+// Data members
+       WIN32_FIND_DATA m_fd;
+       TCHAR m_lpszRoot[MAX_PATH];
+       TCHAR m_chDirSeparator;
+       HANDLE m_hFind;
+       BOOL m_bFound;
+
+// Constructor/destructor
+       CFindFile() : m_hFind(NULL), m_chDirSeparator(_T('\\')), m_bFound(FALSE)
+       { }
+
+       ~CFindFile()
+       {
+               Close();
+       }
+
+// Attributes
+       ULONGLONG GetFileSize() const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               ULARGE_INTEGER nFileSize = { 0 };
+
+               if(m_bFound)
+               {
+                       nFileSize.LowPart = m_fd.nFileSizeLow;
+                       nFileSize.HighPart = m_fd.nFileSizeHigh;
+               }
+               else
+               {
+                       nFileSize.QuadPart = 0;
+               }
+
+               return nFileSize.QuadPart;
+       }
+
+       BOOL GetFileName(LPTSTR lpstrFileName, int cchLength) const
+       {
+               ATLASSERT(m_hFind != NULL);
+               if(lstrlen(m_fd.cFileName) >= cchLength)
+                       return FALSE;
+
+               if(m_bFound)
+                       SecureHelper::strcpy_x(lpstrFileName, cchLength, m_fd.cFileName);
+
+               return m_bFound;
+       }
+
+       BOOL GetFilePath(LPTSTR lpstrFilePath, int cchLength) const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               int nLen = lstrlen(m_lpszRoot);
+#ifndef _WIN32_WCE
+               ATLASSERT(nLen > 0);
+               if(nLen == 0)
+                       return FALSE;
+
+               bool bAddSep = (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/'));
+#else // CE specific
+               // allow diskless devices (nLen == 0)
+               bool bAddSep = ((nLen == 0) || (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/')));
+#endif // _WIN32_WCE
+
+               if((lstrlen(m_lpszRoot) + (bAddSep ?  1 : 0)) >= cchLength)
+                       return FALSE;
+
+               SecureHelper::strcpy_x(lpstrFilePath, cchLength, m_lpszRoot);
+
+               if(bAddSep)
+               {
+                       TCHAR szSeparator[2] = { m_chDirSeparator, 0 };
+                       SecureHelper::strcat_x(lpstrFilePath, cchLength, szSeparator);
+               }
+
+               SecureHelper::strcat_x(lpstrFilePath, cchLength, m_fd.cFileName);
+
+               return TRUE;
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetFileTitle(LPTSTR lpstrFileTitle, int cchLength) const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               TCHAR szBuff[MAX_PATH] = { 0 };
+               if(!GetFileName(szBuff, MAX_PATH))
+                       return FALSE;
+
+               if(lstrlen(szBuff) >= cchLength || cchLength < 1)
+                       return FALSE;
+
+               // find the last dot
+               LPTSTR pstrDot  = (LPTSTR)_cstrrchr(szBuff, _T('.'));
+               if(pstrDot != NULL)
+                       *pstrDot = 0;
+
+               SecureHelper::strcpy_x(lpstrFileTitle, cchLength, szBuff);
+
+               return TRUE;
+       }
+#endif // !_WIN32_WCE
+
+       BOOL GetFileURL(LPTSTR lpstrFileURL, int cchLength) const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               TCHAR szBuff[MAX_PATH] = { 0 };
+               if(!GetFilePath(szBuff, MAX_PATH))
+                       return FALSE;
+               LPCTSTR lpstrFileURLPrefix = _T("file://");
+               if(lstrlen(szBuff) + lstrlen(lpstrFileURLPrefix) >= cchLength)
+                       return FALSE;
+               SecureHelper::strcpy_x(lpstrFileURL, cchLength, lpstrFileURLPrefix);
+               SecureHelper::strcat_x(lpstrFileURL, cchLength, szBuff);
+
+               return TRUE;
+       }
+
+       BOOL GetRoot(LPTSTR lpstrRoot, int cchLength) const
+       {
+               ATLASSERT(m_hFind != NULL);
+               if(lstrlen(m_lpszRoot) >= cchLength)
+                       return FALSE;
+
+               SecureHelper::strcpy_x(lpstrRoot, cchLength, m_lpszRoot);
+
+               return TRUE;
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       _CSTRING_NS::CString GetFileName() const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               _CSTRING_NS::CString ret;
+
+               if(m_bFound)
+                       ret = m_fd.cFileName;
+               return ret;
+       }
+
+       _CSTRING_NS::CString GetFilePath() const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               _CSTRING_NS::CString strResult = m_lpszRoot;
+               int nLen = strResult.GetLength();
+#ifndef _WIN32_WCE
+               ATLASSERT(nLen > 0);
+               if(nLen == 0)
+                       return strResult;
+
+               if((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/')))
+#else // CE specific
+               // allow diskless devices (nLen == 0)
+               if((nLen == 0) || ((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/'))))
+#endif // _WIN32_WCE
+                       strResult += m_chDirSeparator;
+               strResult += GetFileName();
+               return strResult;
+       }
+
+#ifndef _WIN32_WCE
+       _CSTRING_NS::CString GetFileTitle() const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               _CSTRING_NS::CString strResult;
+               GetFileTitle(strResult.GetBuffer(MAX_PATH), MAX_PATH);
+               strResult.ReleaseBuffer();
+
+               return strResult;
+       }
+#endif // !_WIN32_WCE
+
+       _CSTRING_NS::CString GetFileURL() const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               _CSTRING_NS::CString strResult("file://");
+               strResult += GetFilePath();
+               return strResult;
+       }
+
+       _CSTRING_NS::CString GetRoot() const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               _CSTRING_NS::CString str = m_lpszRoot;
+               return str;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       BOOL GetLastWriteTime(FILETIME* pTimeStamp) const
+       {
+               ATLASSERT(m_hFind != NULL);
+               ATLASSERT(pTimeStamp != NULL);
+
+               if(m_bFound && pTimeStamp != NULL)
+               {
+                       *pTimeStamp = m_fd.ftLastWriteTime;
+                       return TRUE;
+               }
+
+               return FALSE;
+       }
+
+       BOOL GetLastAccessTime(FILETIME* pTimeStamp) const
+       {
+               ATLASSERT(m_hFind != NULL);
+               ATLASSERT(pTimeStamp != NULL);
+
+               if(m_bFound && pTimeStamp != NULL)
+               {
+                       *pTimeStamp = m_fd.ftLastAccessTime;
+                       return TRUE;
+               }
+
+               return FALSE;
+       }
+
+       BOOL GetCreationTime(FILETIME* pTimeStamp) const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               if(m_bFound && pTimeStamp != NULL)
+               {
+                       *pTimeStamp = m_fd.ftCreationTime;
+                       return TRUE;
+               }
+
+               return FALSE;
+       }
+
+       BOOL MatchesMask(DWORD dwMask) const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               if(m_bFound)
+                       return ((m_fd.dwFileAttributes & dwMask) != 0);
+
+               return FALSE;
+       }
+
+       BOOL IsDots() const
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               // return TRUE if the file name is "." or ".." and
+               // the file is a directory
+
+               BOOL bResult = FALSE;
+               if(m_bFound && IsDirectory())
+               {
+                       if(m_fd.cFileName[0] == _T('.') && (m_fd.cFileName[1] == _T('\0') || (m_fd.cFileName[1] == _T('.') && m_fd.cFileName[2] == _T('\0'))))
+                               bResult = TRUE;
+               }
+
+               return bResult;
+       }
+
+       BOOL IsReadOnly() const
+       {
+               return MatchesMask(FILE_ATTRIBUTE_READONLY);
+       }
+
+       BOOL IsDirectory() const
+       {
+               return MatchesMask(FILE_ATTRIBUTE_DIRECTORY);
+       }
+
+       BOOL IsCompressed() const
+       {
+               return MatchesMask(FILE_ATTRIBUTE_COMPRESSED);
+       }
+
+       BOOL IsSystem() const
+       {
+               return MatchesMask(FILE_ATTRIBUTE_SYSTEM);
+       }
+
+       BOOL IsHidden() const
+       {
+               return MatchesMask(FILE_ATTRIBUTE_HIDDEN);
+       }
+
+       BOOL IsTemporary() const
+       {
+               return MatchesMask(FILE_ATTRIBUTE_TEMPORARY);
+       }
+
+       BOOL IsNormal() const
+       {
+               return MatchesMask(FILE_ATTRIBUTE_NORMAL);
+       }
+
+       BOOL IsArchived() const
+       {
+               return MatchesMask(FILE_ATTRIBUTE_ARCHIVE);
+       }
+
+// Operations
+       BOOL FindFile(LPCTSTR pstrName = NULL)
+       {
+               Close();
+
+               if(pstrName == NULL)
+               {
+                       pstrName = _T("*.*");
+               }
+               else if(lstrlen(pstrName) >= MAX_PATH)
+               {
+                       ATLASSERT(FALSE);
+                       return FALSE;
+               }
+
+               SecureHelper::strcpy_x(m_fd.cFileName, _countof(m_fd.cFileName), pstrName);
+
+               m_hFind = ::FindFirstFile(pstrName, &m_fd);
+
+               if(m_hFind == INVALID_HANDLE_VALUE)
+                       return FALSE;
+
+#ifndef _WIN32_WCE
+               bool bFullPath = (::GetFullPathName(pstrName, MAX_PATH, m_lpszRoot, NULL) != 0);
+#else // CE specific
+               errno_t nRet = SecureHelper::strncpy_x(m_lpszRoot, _countof(m_lpszRoot), pstrName, _TRUNCATE);
+               bool bFullPath = (nRet == 0 || nRet == STRUNCATE);
+#endif // _WIN32_WCE
+
+               // passed name isn't a valid path but was found by the API
+               ATLASSERT(bFullPath);
+               if(!bFullPath)
+               {
+                       Close();
+                       ::SetLastError(ERROR_INVALID_NAME);
+                       return FALSE;
+               }
+               else
+               {
+                       // find the last forward or backward whack
+                       LPTSTR pstrBack  = (LPTSTR)_cstrrchr(m_lpszRoot, _T('\\'));
+                       LPTSTR pstrFront = (LPTSTR)_cstrrchr(m_lpszRoot, _T('/'));
+
+                       if(pstrFront != NULL || pstrBack != NULL)
+                       {
+                               if(pstrFront == NULL)
+                                       pstrFront = m_lpszRoot;
+                               if(pstrBack == NULL)
+                                       pstrBack = m_lpszRoot;
+
+                               // from the start to the last whack is the root
+
+                               if(pstrFront >= pstrBack)
+                                       *pstrFront = _T('\0');
+                               else
+                                       *pstrBack = _T('\0');
+                       }
+               }
+
+               m_bFound = TRUE;
+
+               return TRUE;
+       }
+
+       BOOL FindNextFile()
+       {
+               ATLASSERT(m_hFind != NULL);
+
+               if(m_hFind == NULL)
+                       return FALSE;
+
+               if(!m_bFound)
+                       return FALSE;
+
+               m_bFound = ::FindNextFile(m_hFind, &m_fd);
+
+               return m_bFound;
+       }
+
+       void Close()
+       {
+               m_bFound = FALSE;
+
+               if(m_hFind != NULL && m_hFind != INVALID_HANDLE_VALUE)
+               {
+                       ::FindClose(m_hFind);
+                       m_hFind = NULL;
+               }
+       }
+
+// Helper
+       static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch)
+       {
+#ifdef _ATL_MIN_CRT
+               const TCHAR* lpsz = NULL;
+               while (*p != 0)
+               {
+                       if (*p == ch)
+                               lpsz = p;
+                       p = ::CharNext(p);
+               }
+               return lpsz;
+#else // !_ATL_MIN_CRT
+               return _tcsrchr(p, ch);
+#endif // !_ATL_MIN_CRT
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Global functions for loading resources
+
+inline HACCEL AtlLoadAccelerators(ATL::_U_STRINGorID table)
+{
+       return ::LoadAccelerators(ModuleHelper::GetResourceInstance(), table.m_lpstr);
+}
+
+inline HMENU AtlLoadMenu(ATL::_U_STRINGorID menu)
+{
+       return ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr);
+}
+
+inline HBITMAP AtlLoadBitmap(ATL::_U_STRINGorID bitmap)
+{
+       return ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr);
+}
+
+#ifdef OEMRESOURCE
+inline HBITMAP AtlLoadSysBitmap(ATL::_U_STRINGorID bitmap)
+{
+#ifdef _DEBUG
+       WORD wID = (WORD)bitmap.m_lpstr;
+       ATLASSERT(wID >= 32734 && wID <= 32767);
+#endif // _DEBUG
+       return ::LoadBitmap(NULL, bitmap.m_lpstr);
+}
+#endif // OEMRESOURCE
+
+inline HCURSOR AtlLoadCursor(ATL::_U_STRINGorID cursor)
+{
+       return ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr);
+}
+
+inline HCURSOR AtlLoadSysCursor(LPCTSTR lpCursorName)
+{
+#if (WINVER >= 0x0500)
+       ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT ||
+               lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE ||
+               lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW ||
+               lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL ||
+               lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP ||
+               lpCursorName == IDC_HAND);
+#else // !(WINVER >= 0x0500)
+       ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT ||
+               lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE ||
+               lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW ||
+               lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL ||
+               lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP);
+#endif // !(WINVER >= 0x0500)
+       return ::LoadCursor(NULL, lpCursorName);
+}
+
+inline HICON AtlLoadIcon(ATL::_U_STRINGorID icon)
+{
+       return ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr);
+}
+
+#ifndef _WIN32_WCE
+inline HICON AtlLoadSysIcon(LPCTSTR lpIconName)
+{
+#if (WINVER >= 0x0600)
+       ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION ||
+                 lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO ||
+                 lpIconName == IDI_SHIELD);
+#else // !(WINVER >= 0x0600)
+       ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION ||
+                 lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO);
+#endif // !(WINVER >= 0x0600)
+       return ::LoadIcon(NULL, lpIconName);
+}
+#endif // !_WIN32_WCE
+
+inline HBITMAP AtlLoadBitmapImage(ATL::_U_STRINGorID bitmap, UINT fuLoad = LR_DEFAULTCOLOR)
+{
+       return (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, IMAGE_BITMAP, 0, 0, fuLoad);
+}
+
+inline HCURSOR AtlLoadCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0)
+{
+       return (HCURSOR)::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad);
+}
+
+inline HICON AtlLoadIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0)
+{
+       return (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad);
+}
+
+#ifdef OEMRESOURCE
+inline HBITMAP AtlLoadSysBitmapImage(WORD wBitmapID, UINT fuLoad = LR_DEFAULTCOLOR)
+{
+       ATLASSERT(wBitmapID >= 32734 && wBitmapID <= 32767);
+       ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0);   // this one doesn't load from a file
+       return (HBITMAP)::LoadImage(NULL, MAKEINTRESOURCE(wBitmapID), IMAGE_BITMAP, 0, 0, fuLoad);
+}
+#endif // OEMRESOURCE
+
+inline HCURSOR AtlLoadSysCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0)
+{
+#ifdef _DEBUG
+       WORD wID = (WORD)cursor.m_lpstr;
+       ATLASSERT((wID >= 32512 && wID <= 32516) || (wID >= 32640 && wID <= 32648) || (wID == 32650) || (wID == 32651));
+       ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0);   // this one doesn't load from a file
+#endif // _DEBUG
+       return (HCURSOR)::LoadImage(NULL, cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad);
+}
+
+inline HICON AtlLoadSysIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0)
+{
+#ifdef _DEBUG
+       WORD wID = (WORD)icon.m_lpstr;
+       ATLASSERT(wID >= 32512 && wID <= 32517);
+       ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0);   // this one doesn't load from a file
+#endif // _DEBUG
+       return (HICON)::LoadImage(NULL, icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad);
+}
+
+#if (_ATL_VER < 0x0700)
+inline int AtlLoadString(UINT uID, LPTSTR lpBuffer, int nBufferMax)
+{
+       return ::LoadString(_Module.GetResourceInstance(), uID, lpBuffer, nBufferMax);
+}
+#endif // (_ATL_VER < 0x0700)
+
+#ifdef _WIN32_WCE // CE only direct access to the resource
+inline LPCTSTR AtlLoadString(UINT uID)
+{
+       LPCTSTR s = (LPCTSTR)::LoadString(ModuleHelper::GetResourceInstance(), uID, NULL, 0);
+#ifdef DEBUG // Check for null-termination
+       if(s != NULL)
+               // Note: RC -n <file.rc> compiles null-terminated resource strings
+               ATLASSERT(s[*((WORD*)s -1) - 1] == L'\0');
+#endif
+       return s;
+}
+#endif // _WIN32_WCE
+
+inline bool AtlLoadString(UINT uID, BSTR& bstrText)
+{
+       USES_CONVERSION;
+       ATLASSERT(bstrText == NULL);
+
+       LPTSTR lpstrText = NULL;
+       int nRes = 0;
+       for(int nLen = 256; ; nLen *= 2)
+       {
+               ATLTRY(lpstrText = new TCHAR[nLen]);
+               if(lpstrText == NULL)
+                       break;
+               nRes = ::LoadString(ModuleHelper::GetResourceInstance(), uID, lpstrText, nLen);
+               if(nRes < nLen - 1)
+                       break;
+               delete [] lpstrText;
+               lpstrText = NULL;
+       }
+
+       if(lpstrText != NULL)
+       {
+               if(nRes != 0)
+                       bstrText = ::SysAllocString(T2OLE(lpstrText));
+               delete [] lpstrText;
+       }
+
+       return (bstrText != NULL) ? true : false;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Global functions for stock GDI objects
+
+inline HPEN AtlGetStockPen(int nPen)
+{
+#if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE)
+       ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN);
+#else
+       ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN);
+#endif
+       return (HPEN)::GetStockObject(nPen);
+}
+
+inline HBRUSH AtlGetStockBrush(int nBrush)
+{
+#if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE)
+       ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH);
+#else
+       ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH);
+#endif
+       return (HBRUSH)::GetStockObject(nBrush);
+}
+
+inline HFONT AtlGetStockFont(int nFont)
+{
+#ifndef _WIN32_WCE
+       ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT);
+#else // CE specific
+       ATLASSERT(nFont == SYSTEM_FONT);
+#endif // _WIN32_WCE
+       return (HFONT)::GetStockObject(nFont);
+}
+
+inline HPALETTE AtlGetStockPalette(int nPalette)
+{
+       ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported
+       return (HPALETTE)::GetStockObject(nPalette);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Global function for compacting a path by replacing parts with ellipsis
+
+// helper for multi-byte character sets
+inline bool _IsDBCSTrailByte(LPCTSTR lpstr, int nChar)
+{
+#ifndef _UNICODE
+       int i = nChar;
+       for( ; i > 0; i--)
+       {
+               if(!::IsDBCSLeadByte(lpstr[i - 1]))
+                       break;
+       }
+       return ((nChar > 0) && (((nChar - i) & 1) != 0));
+#else // _UNICODE
+       lpstr; nChar;
+       return false;
+#endif // _UNICODE
+}
+
+inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen)
+{
+       ATLASSERT(lpstrOut != NULL);
+       ATLASSERT(lpstrIn != NULL);
+       ATLASSERT(cchLen > 0);
+
+       LPCTSTR szEllipsis = _T("...");
+       const int cchEndEllipsis = 3;
+       const int cchMidEllipsis = 4;
+
+       if(lstrlen(lpstrIn) < cchLen)
+       {
+               SecureHelper::strcpy_x(lpstrOut, cchLen, lpstrIn);
+               return true;
+       }
+
+       lpstrOut[0] = 0;
+
+       // check if the separator is a slash or a backslash
+       TCHAR chSlash = _T('\\');
+       for(LPTSTR lpstr = (LPTSTR)lpstrIn; *lpstr != 0; lpstr = ::CharNext(lpstr))
+       {
+               if((*lpstr == _T('/')) || (*lpstr == _T('\\')))
+                       chSlash = *lpstr;
+       }
+
+       // find the filename portion of the path
+       LPCTSTR lpstrFileName = lpstrIn;
+       for(LPCTSTR pPath = lpstrIn; *pPath; pPath = ::CharNext(pPath))
+       {
+               if((pPath[0] == _T('\\') || pPath[0] == _T(':') || pPath[0] == _T('/'))
+                               && pPath[1] && pPath[1] != _T('\\') && pPath[1] != _T('/'))
+                       lpstrFileName = pPath + 1;
+       }
+       int cchFileName = lstrlen(lpstrFileName);
+
+       // handle just the filename without a path
+       if(lpstrFileName == lpstrIn && cchLen > cchEndEllipsis)
+       {
+               bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchLen - cchEndEllipsis - 1) == 0);
+               if(bRet)
+               {
+#ifndef _UNICODE
+                       if(_IsDBCSTrailByte(lpstrIn, cchLen - cchEndEllipsis))
+                               lpstrOut[cchLen - cchEndEllipsis - 1] = 0;
+#endif // _UNICODE
+                       SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis);
+               }
+               return bRet;
+       }
+
+       // handle just ellipsis
+       if((cchLen < (cchMidEllipsis + cchEndEllipsis)))
+       {
+               for(int i = 0; i < cchLen - 1; i++)
+                       lpstrOut[i] = ((i + 1) == cchMidEllipsis) ? chSlash : _T('.');
+               lpstrOut[cchLen - 1] = 0;
+               return true;
+       }
+
+       // calc how much we have to copy
+       int cchToCopy = cchLen - (cchMidEllipsis + cchFileName) - 1;
+
+       if(cchToCopy < 0)
+               cchToCopy = 0;
+
+#ifndef _UNICODE
+       if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrIn, cchToCopy))
+               cchToCopy--;
+#endif // _UNICODE
+
+       bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchToCopy) == 0);
+       if(!bRet)
+               return false;
+
+       // add ellipsis
+       SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis);
+       if(!bRet)
+               return false;
+       TCHAR szSlash[2] = { chSlash, 0 };
+       SecureHelper::strcat_x(lpstrOut, cchLen, szSlash);
+       if(!bRet)
+               return false;
+
+       // add filename (and ellipsis, if needed)
+       if(cchLen > (cchMidEllipsis + cchFileName))
+       {
+               SecureHelper::strcat_x(lpstrOut, cchLen, lpstrFileName);
+       }
+       else
+       {
+               cchToCopy = cchLen - cchMidEllipsis - cchEndEllipsis - 1;
+#ifndef _UNICODE
+               if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrFileName, cchToCopy))
+                       cchToCopy--;
+#endif // _UNICODE
+               bRet = (SecureHelper::strncpy_x(&lpstrOut[cchMidEllipsis], cchLen - cchMidEllipsis, lpstrFileName, cchToCopy) == 0);
+               if(bRet)
+                       SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis);
+       }
+
+       return bRet;
+}
+
+}; // namespace WTL
+
+#endif // __ATLMISC_H__
diff --git a/include/WTL/Include/atlprint.h b/include/WTL/Include/atlprint.h
new file mode 100644 (file)
index 0000000..5b81b2b
--- /dev/null
@@ -0,0 +1,1113 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLPRINT_H__
+#define __ATLPRINT_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifdef _WIN32_WCE
+       #error atlprint.h is not supported on Windows CE
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlprint.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atlprint.h requires atlwin.h to be included first
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CPrinterInfo<t_nInfo>
+// CPrinterT<t_bManaged>
+// CDevModeT<t_bManaged>
+// CPrinterDC
+// CPrintJobInfo
+// CPrintJob
+// CPrintPreview
+// CPrintPreviewWindowImpl<T, TBase, TWinTraits>
+// CPrintPreviewWindow
+// CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits>
+// CZoomPrintPreviewWindow
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures
+//                and provided by ::GetPrinter.
+
+template <unsigned int t_nInfo>
+class _printer_info
+{
+public:
+       typedef void infotype;
+};
+
+template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; };
+template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; };
+template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; };
+template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; };
+template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; };
+template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; };
+template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; };
+// these are not in the old (vc6.0) headers
+#ifdef _ATL_USE_NEW_PRINTER_INFO
+template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; };
+template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; };
+#endif // _ATL_USE_NEW_PRINTER_INFO
+
+
+template <unsigned int t_nInfo>
+class CPrinterInfo
+{
+public:
+// Data members
+       typename _printer_info<t_nInfo>::infotype* m_pi;
+
+// Constructor/destructor
+       CPrinterInfo() : m_pi(NULL)
+       { }
+
+       CPrinterInfo(HANDLE hPrinter) : m_pi(NULL)
+       {
+               GetPrinterInfo(hPrinter);
+       }
+
+       ~CPrinterInfo()
+       {
+               Cleanup();
+       }
+
+// Operations
+       bool GetPrinterInfo(HANDLE hPrinter)
+       {
+               Cleanup();
+               return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo);
+       }
+
+// Implementation
+       void Cleanup()
+       {
+               delete [] (BYTE*)m_pi;
+               m_pi = NULL;
+       }
+
+       static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex)
+       {
+               ATLASSERT(pi != NULL);
+               DWORD dw = 0;
+               BYTE* pb = NULL;
+               ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw);
+               if (dw > 0)
+               {
+                       ATLTRY(pb = new BYTE[dw]);
+                       if (pb != NULL)
+                       {
+                               memset(pb, 0, dw);
+                               DWORD dwNew;
+                               if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew))
+                               {
+                                       delete [] pb;
+                                       pb = NULL;
+                               }
+                       }
+               }
+               *pi = pb;
+               return (pb != NULL);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPrinter - Wrapper class for a HANDLE to a printer
+
+template <bool t_bManaged>
+class CPrinterT
+{
+public:
+// Data members
+       HANDLE m_hPrinter;
+
+// Constructor/destructor
+       CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter)
+       { }
+
+       ~CPrinterT()
+       {
+               ClosePrinter();
+       }
+
+// Operations
+       CPrinterT& operator =(HANDLE hPrinter)
+       {
+               if (hPrinter != m_hPrinter)
+               {
+                       ClosePrinter();
+                       m_hPrinter = hPrinter;
+               }
+               return *this;
+       }
+
+       bool IsNull() const { return (m_hPrinter == NULL); }
+
+       bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL)
+       {
+               bool b = false;
+               DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames);
+               if (pdn != NULL)
+               {
+                       LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset;
+                       b = OpenPrinter(lpszPrinterName, pDevMode);
+                       ::GlobalUnlock(hDevNames);
+               }
+               return b;
+       }
+
+       bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL)
+       {
+               ClosePrinter();
+               PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
+               ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
+
+               return (m_hPrinter != NULL);
+       }
+
+       bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs)
+       {
+               ClosePrinter();
+               ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs);
+               return (m_hPrinter != NULL);
+       }
+
+       bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL)
+       {
+               ClosePrinter();
+               const int cchBuff = 512;
+               TCHAR buffer[cchBuff];
+               buffer[0] = 0;
+               ::GetProfileString(_T("windows"), _T("device"), _T(",,,"), buffer, cchBuff);
+               int nLen = lstrlen(buffer);
+               if (nLen != 0)
+               {
+                       LPTSTR lpsz = buffer;
+                       while (*lpsz)
+                       {
+                               if (*lpsz == _T(','))
+                               {
+                                       *lpsz = 0;
+                                       break;
+                               }
+                               lpsz = CharNext(lpsz);
+                       }
+                       PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
+                       ::OpenPrinter(buffer, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
+               }
+               return m_hPrinter != NULL;
+       }
+
+       void ClosePrinter()
+       {
+               if (m_hPrinter != NULL)
+               {
+                       if (t_bManaged)
+                               ::ClosePrinter(m_hPrinter);
+                       m_hPrinter = NULL;
+               }
+       }
+
+       bool PrinterProperties(HWND hWnd = NULL)
+       {
+               if (hWnd == NULL)
+                       hWnd = ::GetActiveWindow();
+               return !!::PrinterProperties(hWnd, m_hPrinter);
+       }
+
+       HANDLE CopyToHDEVNAMES() const
+       {
+               HANDLE h = NULL;
+               CPrinterInfo<5> pinfon5;
+               CPrinterInfo<2> pinfon2;
+               LPTSTR lpszPrinterName = NULL;
+               // Some printers fail for PRINTER_INFO_5 in some situations
+               if (pinfon5.GetPrinterInfo(m_hPrinter))
+                       lpszPrinterName = pinfon5.m_pi->pPrinterName;
+               else if (pinfon2.GetPrinterInfo(m_hPrinter))
+                       lpszPrinterName = pinfon2.m_pi->pPrinterName;
+               if (lpszPrinterName != NULL)
+               {
+                       int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR);
+                       h = ::GlobalAlloc(GMEM_MOVEABLE, nLen);
+                       BYTE* pv = (BYTE*)::GlobalLock(h);
+                       DEVNAMES* pdev = (DEVNAMES*)pv;
+                       if (pv != NULL)
+                       {
+                               memset(pv, 0, nLen);
+                               pdev->wDeviceOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
+                               pv = pv + sizeof(DEVNAMES); // now points to end
+                               SecureHelper::strcpy_x((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName);
+                               ::GlobalUnlock(h);
+                       }
+               }
+               return h;
+       }
+
+       HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const
+       {
+               CPrinterInfo<5> pinfo5;
+               CPrinterInfo<2> pinfo2;
+               HDC hDC = NULL;
+               LPTSTR lpszPrinterName = NULL;
+               // Some printers fail for PRINTER_INFO_5 in some situations
+               if (pinfo5.GetPrinterInfo(m_hPrinter))
+                       lpszPrinterName = pinfo5.m_pi->pPrinterName;
+               else if (pinfo2.GetPrinterInfo(m_hPrinter))
+                       lpszPrinterName = pinfo2.m_pi->pPrinterName;
+               if (lpszPrinterName != NULL)
+                       hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm);
+               return hDC;
+       }
+
+       HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const
+       {
+               CPrinterInfo<5> pinfo5;
+               CPrinterInfo<2> pinfo2;
+               HDC hDC = NULL;
+               LPTSTR lpszPrinterName = NULL;
+               // Some printers fail for PRINTER_INFO_5 in some situations
+               if (pinfo5.GetPrinterInfo(m_hPrinter))
+                       lpszPrinterName = pinfo5.m_pi->pPrinterName;
+               else if (pinfo2.GetPrinterInfo(m_hPrinter))
+                       lpszPrinterName = pinfo2.m_pi->pPrinterName;
+               if (lpszPrinterName != NULL)
+                       hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm);
+               return hDC;
+       }
+
+       void Attach(HANDLE hPrinter)
+       {
+               ClosePrinter();
+               m_hPrinter = hPrinter;
+       }
+
+       HANDLE Detach()
+       {
+               HANDLE hPrinter = m_hPrinter;
+               m_hPrinter = NULL;
+               return hPrinter;
+       }
+
+       operator HANDLE() const { return m_hPrinter; }
+};
+
+typedef CPrinterT<false>   CPrinterHandle;
+typedef CPrinterT<true>    CPrinter;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CDevMode - Wrapper class for DEVMODE
+
+template <bool t_bManaged>
+class CDevModeT
+{
+public:
+// Data members
+       HANDLE m_hDevMode;
+       DEVMODE* m_pDevMode;
+
+// Constructor/destructor
+       CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode)
+       {
+               m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
+       }
+
+       ~CDevModeT()
+       {
+               Cleanup();
+       }
+
+// Operations
+       CDevModeT<t_bManaged>& operator =(HANDLE hDevMode)
+       {
+               Attach(hDevMode);
+               return *this;
+       }
+
+       void Attach(HANDLE hDevModeNew)
+       {
+               Cleanup();
+               m_hDevMode = hDevModeNew;
+               m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
+       }
+
+       HANDLE Detach()
+       {
+               if (m_hDevMode != NULL)
+                       ::GlobalUnlock(m_hDevMode);
+               HANDLE hDevMode = m_hDevMode;
+               m_hDevMode = NULL;
+               return hDevMode;
+       }
+
+       bool IsNull() const { return (m_hDevMode == NULL); }
+
+       bool CopyFromPrinter(HANDLE hPrinter)
+       {
+               CPrinterInfo<2> pinfo;
+               bool b = pinfo.GetPrinterInfo(hPrinter);
+               if (b)
+                b = CopyFromDEVMODE(pinfo.m_pi->pDevMode);
+               return b;
+       }
+
+       bool CopyFromDEVMODE(const DEVMODE* pdm)
+       {
+               if (pdm == NULL)
+                       return false;
+               int nSize = pdm->dmSize + pdm->dmDriverExtra;
+               HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
+               if (h != NULL)
+               {
+                       void* p = ::GlobalLock(h);
+                       SecureHelper::memcpy_x(p, nSize, pdm, nSize);
+                       ::GlobalUnlock(h);
+               }
+               Attach(h);
+               return (h != NULL);
+       }
+
+       bool CopyFromHDEVMODE(HANDLE hdm)
+       {
+               bool b = false;
+               if (hdm != NULL)
+               {
+                       DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm);
+                       b = CopyFromDEVMODE(pdm);
+                       ::GlobalUnlock(hdm);
+               }
+               return b;
+       }
+
+       HANDLE CopyToHDEVMODE()
+       {
+               if ((m_hDevMode == NULL) || (m_pDevMode == NULL))
+                       return NULL;
+               int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra;
+               HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
+               if (h != NULL)
+               {
+                       void* p = ::GlobalLock(h);
+                       SecureHelper::memcpy_x(p, nSize, m_pDevMode, nSize);
+                       ::GlobalUnlock(h);
+               }
+               return h;
+       }
+
+       // If this devmode was for another printer, this will create a new devmode
+       // based on the existing devmode, but retargeted at the new printer
+       bool UpdateForNewPrinter(HANDLE hPrinter)
+       {
+               bool bRet = false;
+               LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0);
+               CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               DEVMODE* pdm = buff.AllocateBytes(nLen);
+               if(pdm != NULL)
+               {
+                       memset(pdm, 0, nLen);
+                       LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
+                       if (l == IDOK)
+                               bRet = CopyFromDEVMODE(pdm);
+               }
+
+               return bRet;
+       }
+
+       bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL)
+       {
+               CPrinterInfo<1> pi;
+               pi.GetPrinterInfo(hPrinter);
+               if (hWnd == NULL)
+                       hWnd = ::GetActiveWindow();
+
+               bool bRet = false;
+               LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0);
+               CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               DEVMODE* pdm = buff.AllocateBytes(nLen);
+               if(pdm != NULL)
+               {
+                       memset(pdm, 0, nLen);
+                       LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT);
+                       if (l == IDOK)
+                               bRet = CopyFromDEVMODE(pdm);
+               }
+
+               return bRet;
+       }
+
+       operator HANDLE() const { return m_hDevMode; }
+
+       operator DEVMODE*() const { return m_pDevMode; }
+
+// Implementation
+       void Cleanup()
+       {
+               if (m_hDevMode != NULL)
+               {
+                       ::GlobalUnlock(m_hDevMode);
+                       if(t_bManaged)
+                               ::GlobalFree(m_hDevMode);
+                       m_hDevMode = NULL;
+               }
+       }
+};
+
+typedef CDevModeT<false>   CDevModeHandle;
+typedef CDevModeT<true>    CDevMode;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPrinterDC
+
+class CPrinterDC : public CDC
+{
+public:
+// Constructors/destructor
+       CPrinterDC()
+       {
+               CPrinter printer;
+               printer.OpenDefaultPrinter();
+               Attach(printer.CreatePrinterDC());
+               ATLASSERT(m_hDC != NULL);
+       }
+
+       CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL)
+       {
+               CPrinterHandle p;
+               p.Attach(hPrinter);
+               Attach(p.CreatePrinterDC(pdm));
+               ATLASSERT(m_hDC != NULL);
+       }
+
+       ~CPrinterDC()
+       {
+               DeleteDC();
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc)
+//             Handles aborting, background printing
+
+// Defines callbacks used by CPrintJob (not a COM interface)
+class ATL_NO_VTABLE IPrintJobInfo
+{
+public:
+       virtual void BeginPrintJob(HDC hDC) = 0;                // allocate handles needed, etc.
+       virtual void EndPrintJob(HDC hDC, bool bAborted) = 0;   // free handles, etc.
+       virtual void PrePrintPage(UINT nPage, HDC hDC) = 0;
+       virtual bool PrintPage(UINT nPage, HDC hDC) = 0;
+       virtual void PostPrintPage(UINT nPage, HDC hDC) = 0;
+       // If you want per page devmodes, return the DEVMODE* to use for nPage.
+       // You can optimize by only returning a new DEVMODE* when it is different
+       // from the one for nLastPage, otherwise return NULL.
+       // When nLastPage==0, the current DEVMODE* will be the default passed to
+       // StartPrintJob.
+       // Note: During print preview, nLastPage will always be "0".
+       virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0;
+       virtual bool IsValidPage(UINT nPage) = 0;
+};
+
+// Provides a default implementatin for IPrintJobInfo
+// Typically, MI'd into a document or view class
+class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo
+{
+public:
+       virtual void BeginPrintJob(HDC /*hDC*/)   // allocate handles needed, etc
+       {
+       }
+
+       virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/)   // free handles, etc
+       {
+       }
+
+       virtual void PrePrintPage(UINT /*nPage*/, HDC hDC)
+       {
+               m_nPJState = ::SaveDC(hDC);
+       }
+
+       virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0;
+
+       virtual void PostPrintPage(UINT /*nPage*/, HDC hDC)
+       {
+               RestoreDC(hDC, m_nPJState);
+       }
+
+       virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/)
+       {
+               return NULL;
+       }
+
+       virtual bool IsValidPage(UINT /*nPage*/)
+       {
+               return true;
+       }
+
+// Implementation - data
+       int m_nPJState;
+};
+
+
+class CPrintJob
+{
+public:
+// Data members
+       CPrinterHandle m_printer;
+       IPrintJobInfo* m_pInfo;
+       DEVMODE* m_pDefDevMode;
+       DOCINFO m_docinfo;
+       int m_nJobID;
+       bool m_bCancel;
+       bool m_bComplete;
+       unsigned long m_nStartPage;
+       unsigned long m_nEndPage;
+
+// Constructor/destructor
+       CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true)
+       { }
+
+       ~CPrintJob()
+       {
+               ATLASSERT(IsJobComplete()); // premature destruction?
+       }
+
+// Operations
+       bool IsJobComplete() const
+       {
+               return m_bComplete;
+       }
+
+       bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode,
+                       IPrintJobInfo* pInfo, LPCTSTR lpszDocName, 
+                       unsigned long nStartPage, unsigned long nEndPage,
+                       bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL)
+       {
+               ATLASSERT(m_bComplete); // previous job not done yet?
+               if (pInfo == NULL)
+                       return false;
+
+               memset(&m_docinfo, 0, sizeof(m_docinfo));
+               m_docinfo.cbSize = sizeof(m_docinfo);
+               m_docinfo.lpszDocName = lpszDocName;
+               m_pInfo = pInfo;
+               m_nStartPage = nStartPage;
+               m_nEndPage = nEndPage;
+               m_printer.Attach(hPrinter);
+               m_pDefDevMode = pDefaultDevMode;
+               m_bComplete = false;
+
+               if(bPrintToFile)
+                       m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:");
+
+               if (!bBackground)
+               {
+                       m_bComplete = true;
+                       return StartHelper();
+               }
+
+               // Create a thread and return
+               DWORD dwThreadID = 0;
+#if !defined(_ATL_MIN_CRT) && defined(_MT)
+               HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID);
+#else
+               HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID);
+#endif
+               if (hThread == NULL)
+                       return false;
+
+               ::CloseHandle(hThread);
+
+               return true;
+       }
+
+// Implementation
+       static DWORD WINAPI StartProc(void* p)
+       {
+               CPrintJob* pThis = (CPrintJob*)p;
+               pThis->StartHelper();
+               pThis->m_bComplete = true;
+               return 0;
+       }
+
+       bool StartHelper()
+       {
+               CDC dcPrinter;
+               dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode));
+               if (dcPrinter.IsNull())
+                       return false;
+                       
+               m_nJobID = ::StartDoc(dcPrinter, &m_docinfo);
+               if (m_nJobID <= 0)
+                       return false;
+
+               m_pInfo->BeginPrintJob(dcPrinter);
+
+               // print all the pages now
+               unsigned long nLastPage = 0;
+               for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++)
+               {
+                       if (!m_pInfo->IsValidPage(nPage))
+                               break;
+                       DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage);
+                       if (pdm != NULL)
+                               dcPrinter.ResetDC(pdm);
+                       dcPrinter.StartPage();
+                       m_pInfo->PrePrintPage(nPage, dcPrinter);
+                       if (!m_pInfo->PrintPage(nPage, dcPrinter))
+                               m_bCancel = true;
+                       m_pInfo->PostPrintPage(nPage, dcPrinter);
+                       dcPrinter.EndPage();
+                       if (m_bCancel)
+                               break;
+                       nLastPage = nPage;
+               }
+
+               m_pInfo->EndPrintJob(dcPrinter, m_bCancel);
+               if (m_bCancel)
+                       ::AbortDoc(dcPrinter);
+               else
+                       ::EndDoc(dcPrinter);
+               m_nJobID = 0;
+               return true;
+       }
+
+       // Cancels a print job. Can be called asynchronously.
+       void CancelPrintJob()
+       {
+               m_bCancel = true;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPrintPreview - Adds print preview support to an existing window
+
+class CPrintPreview
+{
+public:
+// Data members
+       IPrintJobInfo* m_pInfo;
+       CPrinterHandle m_printer;
+       CEnhMetaFile m_meta;
+       DEVMODE* m_pDefDevMode;
+       DEVMODE* m_pCurDevMode;
+       SIZE m_sizeCurPhysOffset;
+
+// Constructor
+       CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL)
+       {
+               m_sizeCurPhysOffset.cx = 0;
+               m_sizeCurPhysOffset.cy = 0;
+       }
+
+// Operations
+       void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji)
+       {
+               m_printer.Attach(hPrinter);
+               m_pDefDevMode = pDefaultDevMode;
+               m_pInfo = pji;
+               m_nCurPage = 0;
+               m_pCurDevMode = NULL;
+       }
+
+       void SetEnhMetaFile(HENHMETAFILE hEMF)
+       {
+               m_meta = hEMF;
+       }
+
+       void SetPage(int nPage)
+       {
+               if (!m_pInfo->IsValidPage(nPage))
+                       return;
+               m_nCurPage = nPage;
+               m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage);
+               if (m_pCurDevMode == NULL)
+                       m_pCurDevMode = m_pDefDevMode;
+               CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode);
+
+               int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH); 
+               int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT); 
+               int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX);
+               int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY);
+
+               RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) };
+
+               m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX);
+               m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY);
+               
+               CEnhMetaFileDC dcMeta(dcPrinter, &rcMM);
+               m_pInfo->PrePrintPage(nPage, dcMeta);
+               m_pInfo->PrintPage(nPage, dcMeta);
+               m_pInfo->PostPrintPage(nPage, dcMeta);
+               m_meta.Attach(dcMeta.Close());
+       }
+
+       void GetPageRect(RECT& rc, LPRECT prc)
+       {
+               int x1 = rc.right-rc.left;
+               int y1 = rc.bottom - rc.top;
+               if ((x1 < 0) || (y1 < 0))
+                       return;
+
+               CEnhMetaFileInfo emfinfo(m_meta);
+               ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
+
+               // Compute whether we are OK vertically or horizontally
+               int x2 = pmh->szlDevice.cx;
+               int y2 = pmh->szlDevice.cy;
+               int y1p = MulDiv(x1, y2, x2);
+               int x1p = MulDiv(y1, x2, y2);
+               ATLASSERT((x1p <= x1) || (y1p <= y1));
+               if (x1p <= x1)
+               {
+                       prc->left = rc.left + (x1 - x1p) / 2;
+                       prc->right = prc->left + x1p;
+                       prc->top = rc.top;
+                       prc->bottom = rc.bottom;
+               }
+               else
+               {
+                       prc->left = rc.left;
+                       prc->right = rc.right;
+                       prc->top = rc.top + (y1 - y1p) / 2;
+                       prc->bottom = prc->top + y1p;
+               }
+       }
+
+// Painting helpers
+       void DoPaint(CDCHandle dc)
+       {
+               // this one is not used
+       }
+
+       void DoPaint(CDCHandle dc, RECT& rc)
+       {
+               CEnhMetaFileInfo emfinfo(m_meta);
+               ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
+               int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
+               int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
+
+               dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
+               dc.PlayMetaFile(m_meta, &rc);
+       }
+
+// Implementation - data
+       int m_nCurPage;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CPrintPreviewWindow - Implements a print preview window
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CPrintPreview
+{
+public:
+       DECLARE_WND_CLASS_EX(NULL, CS_VREDRAW | CS_HREDRAW, -1)
+
+       enum { m_cxOffset = 10, m_cyOffset = 10 };
+
+// Constructor
+       CPrintPreviewWindowImpl() : m_nMaxPage(0), m_nMinPage(0)
+       { }
+
+// Operations
+       void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, 
+               IPrintJobInfo* pji, int nMinPage, int nMaxPage)
+       {
+               CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji);
+               m_nMinPage = nMinPage;
+               m_nMaxPage = nMaxPage;
+       }
+
+       bool NextPage()
+       {
+               if (m_nCurPage == m_nMaxPage)
+                       return false;
+               SetPage(m_nCurPage + 1);
+               Invalidate();
+               return true;
+       }
+
+       bool PrevPage()
+       {
+               if (m_nCurPage == m_nMinPage)
+                       return false;
+               if (m_nCurPage == 0)
+                       return false;
+               SetPage(m_nCurPage - 1);
+               Invalidate();
+               return true;
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CPrintPreviewWindowImpl)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+       END_MSG_MAP()
+
+       LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;   // no need for the background
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               RECT rc = { 0 };
+
+               if(wParam != NULL)
+               {
+                       pT->DoPrePaint((HDC)wParam, rc);
+                       pT->DoPaint((HDC)wParam, rc);
+               }
+               else
+               {
+                       CPaintDC dc(m_hWnd);
+                       pT->DoPrePaint(dc.m_hDC, rc);
+                       pT->DoPaint(dc.m_hDC, rc);
+               }
+
+               return 0;
+       }
+
+// Painting helper
+       void DoPrePaint(CDCHandle dc, RECT& rc)
+       {
+               RECT rcClient = { 0 };
+               GetClientRect(&rcClient);
+               RECT rcArea = rcClient;
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+               ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
+               if (rcArea.left > rcArea.right)
+                       rcArea.right = rcArea.left;
+               if (rcArea.top > rcArea.bottom)
+                       rcArea.bottom = rcArea.top;
+               GetPageRect(rcArea, &rc);
+               CRgn rgn1, rgn2;
+               rgn1.CreateRectRgnIndirect(&rc);
+               rgn2.CreateRectRgnIndirect(&rcClient);
+               rgn2.CombineRgn(rgn1, RGN_DIFF);
+               dc.SelectClipRgn(rgn2);
+               dc.FillRect(&rcClient, COLOR_BTNSHADOW);
+               dc.SelectClipRgn(NULL);
+               dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH));
+       }
+
+// Implementation - data
+       int m_nMinPage;
+       int m_nMaxPage;
+};
+
+
+class CPrintPreviewWindow : public CPrintPreviewWindowImpl<CPrintPreviewWindow>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CZoomPrintPreviewWindowImpl - Implements print preview window with zooming
+
+#ifdef __ATLSCRL_H__
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
+{
+public:
+       bool m_bSized;
+
+       CZoomPrintPreviewWindowImpl()  
+       {
+               SetScrollExtendedStyle(SCRL_DISABLENOSCROLL);
+               InitZoom();
+       }
+
+       // should be called to reset data members before recreating window 
+       void InitZoom()
+       {
+               m_bSized = false;       
+               m_nZoomMode = ZOOMMODE_OFF;
+               m_fZoomScaleMin = 1.0;
+               m_fZoomScale = 1.0;
+       }
+
+       BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl)
+               MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
+               MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
+               MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
+               MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
+               MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
+               MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
+               MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
+               COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
+               COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
+       END_MSG_MAP()
+       
+       LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+               POINT ptOffset = m_ptOffset;
+               SIZE sizeAll = m_sizeAll;
+               SetScrollSize(sizeClient);
+               if(sizeAll.cx > 0)
+                       ptOffset.x = ::MulDiv(ptOffset.x, m_sizeAll.cx, sizeAll.cx);
+               if(sizeAll.cy > 0)
+                       ptOffset.y = ::MulDiv(ptOffset.y, m_sizeAll.cy, sizeAll.cy);
+               SetScrollOffset(ptOffset);
+               CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled);
+               if(!m_bSized)
+               {
+                       m_bSized = true;
+                       T* pT = static_cast<T*>(this);
+                       pT->ShowScrollBar(SB_HORZ, TRUE);
+                       pT->ShowScrollBar(SB_VERT, TRUE);
+               }
+               return 0;
+       }
+
+       LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               RECT rc = { 0 };
+
+               if(wParam != NULL)
+               {
+                       CDCHandle dc = (HDC)wParam;
+                       int nMapModeSav = dc.GetMapMode();
+                       dc.SetMapMode(MM_ANISOTROPIC);
+                       SIZE szWindowExt = { 0, 0 };
+                       dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
+                       SIZE szViewportExt = { 0, 0 };
+                       dc.SetViewportExt(m_sizeAll, &szViewportExt);
+                       POINT ptViewportOrg = { 0, 0 };
+                       dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
+
+                       pT->DoPrePaint(dc, rc);
+                       pT->DoPaint(dc, rc);
+
+                       dc.SetMapMode(nMapModeSav);
+                       dc.SetWindowExt(szWindowExt);
+                       dc.SetViewportExt(szViewportExt);
+                       dc.SetViewportOrg(ptViewportOrg);
+               }
+               else
+               {
+                       CPaintDC dc(pT->m_hWnd);
+                       pT->PrepareDC(dc.m_hDC);
+                       pT->DoPrePaint(dc.m_hDC, rc);
+                       pT->DoPaint(dc.m_hDC, rc);
+               }
+
+               return 0;
+       }
+
+       // Painting helpers
+       void DoPaint(CDCHandle dc)
+       {
+               // this one is not used
+       }
+
+       void DoPrePaint(CDCHandle dc, RECT& rc)
+       {
+               RECT rcClient;
+               GetClientRect(&rcClient);
+               RECT rcArea = rcClient;
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+               ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
+               if (rcArea.left > rcArea.right)
+                       rcArea.right = rcArea.left;
+               if (rcArea.top > rcArea.bottom)
+                       rcArea.bottom = rcArea.top;
+               GetPageRect(rcArea, &rc);
+               HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
+               dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY);
+               dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY);
+               dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY);
+               dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY);
+               dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH));
+               dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
+               dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW));
+               dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY);
+               dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY);
+               dc.SelectBrush(hbrOld);
+       }
+
+       void DoPaint(CDCHandle dc, RECT& rc)
+       {
+               CEnhMetaFileInfo emfinfo(m_meta);
+               ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
+               int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
+               int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
+
+               dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
+               dc.PlayMetaFile(m_meta, &rc);
+       }
+};
+
+class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl<CZoomPrintPreviewWindow>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
+};
+
+#endif // __ATLSCRL_H__
+
+}; // namespace WTL
+
+#endif // __ATLPRINT_H__
diff --git a/include/WTL/Include/atlres.h b/include/WTL/Include/atlres.h
new file mode 100644 (file)
index 0000000..b8b3e8f
--- /dev/null
@@ -0,0 +1,262 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLRES_H__
+#define __ATLRES_H__
+
+#pragma once
+
+#if defined(_WIN32_WCE) && !defined(__ATLRESCE_H__)
+       #error Use atlresCE.h instead of atlres.h for Windows CE
+#endif
+
+
+#ifdef RC_INVOKED
+#ifndef _INC_WINDOWS
+
+  #define _INC_WINDOWS
+
+  #ifndef _WIN32_WCE
+    #define VS_VERSION_INFO     1
+
+    #ifdef APSTUDIO_INVOKED
+      #define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols
+    #endif // APSTUDIO_INVOKED
+
+    #ifndef WINVER
+      #define WINVER 0x0400   // default to Windows Version 4.0
+    #endif // !WINVER
+
+    #include <winresrc.h>
+
+    // operation messages sent to DLGINIT
+    #define LB_ADDSTRING    (WM_USER+1)
+    #define CB_ADDSTRING    (WM_USER+3)
+  #endif // !_WIN32_WCE
+
+  #ifdef APSTUDIO_INVOKED
+    #undef APSTUDIO_HIDDEN_SYMBOLS
+  #endif // APSTUDIO_INVOKED
+
+  #ifdef IDC_STATIC
+    #undef IDC_STATIC
+  #endif // IDC_STATIC
+  #define IDC_STATIC      (-1)
+
+#endif // !_INC_WINDOWS
+#endif // RC_INVOKED
+
+#ifdef APSTUDIO_INVOKED
+  #define APSTUDIO_HIDDEN_SYMBOLS
+#endif // APSTUDIO_INVOKED
+
+///////////////////////////////////////////////////////////////////////////////
+// ATL resource types
+
+#ifndef RC_INVOKED
+  #define RT_DLGINIT  MAKEINTRESOURCE(240)
+  #define RT_TOOLBAR  MAKEINTRESOURCE(241)
+#endif // RC_INVOKED
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef APSTUDIO_INVOKED
+  #undef APSTUDIO_HIDDEN_SYMBOLS
+#endif // APSTUDIO_INVOKED
+
+///////////////////////////////////////////////////////////////////////////////
+// Standard window components
+
+#define ID_SEPARATOR                    0       // special separator value
+#define ID_DEFAULT_PANE                 0       // default status bar pane
+
+#ifndef RC_INVOKED  // code only
+// standard control bars (IDW = window ID)
+  #define ATL_IDW_TOOLBAR               0xE800  // main Toolbar for window
+  #define ATL_IDW_STATUS_BAR            0xE801  // Status bar window
+  #define ATL_IDW_COMMAND_BAR           0xE802  // Command bar window
+
+// parts of a frame window
+  #define ATL_IDW_CLIENT                0xE900
+  #define ATL_IDW_PANE_FIRST            0xE900  // first pane (256 max)
+  #define ATL_IDW_PANE_LAST             0xE9FF
+  #define ATL_IDW_HSCROLL_FIRST         0xEA00  // first Horz scrollbar (16 max)
+  #define ATL_IDW_VSCROLL_FIRST         0xEA10  // first Vert scrollbar (16 max)
+
+  #define ATL_IDW_SIZE_BOX              0xEA20  // size box for splitters
+  #define ATL_IDW_PANE_SAVE             0xEA21  // to shift ATL_IDW_PANE_FIRST
+
+// bands for a rebar
+  #define ATL_IDW_BAND_FIRST            0xEB00
+  #define ATL_IDW_BAND_LAST             0xEBFF
+#endif // !RC_INVOKED
+
+///////////////////////////////////////////////////////////////////////////////
+// Standard Commands
+
+// File commands
+#define ID_FILE_NEW                     0xE100
+#define ID_FILE_OPEN                    0xE101
+#define ID_FILE_CLOSE                   0xE102
+#define ID_FILE_SAVE                    0xE103
+#define ID_FILE_SAVE_AS                 0xE104
+#define ID_FILE_PAGE_SETUP              0xE105
+#define ID_FILE_PRINT_SETUP             0xE106
+#define ID_FILE_PRINT                   0xE107
+#define ID_FILE_PRINT_DIRECT            0xE108
+#define ID_FILE_PRINT_PREVIEW           0xE109
+#define ID_FILE_UPDATE                  0xE10A
+#define ID_FILE_SAVE_COPY_AS            0xE10B
+#define ID_FILE_SEND_MAIL               0xE10C
+
+#define ID_FILE_MRU_FIRST               0xE110
+#define ID_FILE_MRU_FILE1               0xE110          // range - 16 max
+#define ID_FILE_MRU_FILE2               0xE111
+#define ID_FILE_MRU_FILE3               0xE112
+#define ID_FILE_MRU_FILE4               0xE113
+#define ID_FILE_MRU_FILE5               0xE114
+#define ID_FILE_MRU_FILE6               0xE115
+#define ID_FILE_MRU_FILE7               0xE116
+#define ID_FILE_MRU_FILE8               0xE117
+#define ID_FILE_MRU_FILE9               0xE118
+#define ID_FILE_MRU_FILE10              0xE119
+#define ID_FILE_MRU_FILE11              0xE11A
+#define ID_FILE_MRU_FILE12              0xE11B
+#define ID_FILE_MRU_FILE13              0xE11C
+#define ID_FILE_MRU_FILE14              0xE11D
+#define ID_FILE_MRU_FILE15              0xE11E
+#define ID_FILE_MRU_FILE16              0xE11F
+#define ID_FILE_MRU_LAST                0xE11F
+
+// Edit commands
+#define ID_EDIT_CLEAR                   0xE120
+#define ID_EDIT_CLEAR_ALL               0xE121
+#define ID_EDIT_COPY                    0xE122
+#define ID_EDIT_CUT                     0xE123
+#define ID_EDIT_FIND                    0xE124
+#define ID_EDIT_PASTE                   0xE125
+#define ID_EDIT_PASTE_LINK              0xE126
+#define ID_EDIT_PASTE_SPECIAL           0xE127
+#define ID_EDIT_REPEAT                  0xE128
+#define ID_EDIT_REPLACE                 0xE129
+#define ID_EDIT_SELECT_ALL              0xE12A
+#define ID_EDIT_UNDO                    0xE12B
+#define ID_EDIT_REDO                    0xE12C
+
+// Window commands
+#define ID_WINDOW_NEW                   0xE130
+#define ID_WINDOW_ARRANGE               0xE131
+#define ID_WINDOW_CASCADE               0xE132
+#define ID_WINDOW_TILE_HORZ             0xE133
+#define ID_WINDOW_TILE_VERT             0xE134
+#define ID_WINDOW_SPLIT                 0xE135
+#ifndef RC_INVOKED      // code only
+  #define ATL_IDM_WINDOW_FIRST          0xE130
+  #define ATL_IDM_WINDOW_LAST           0xE13F
+  #define ATL_IDM_FIRST_MDICHILD        0xFF00  // window list starts here
+  #define ATL_IDM_LAST_MDICHILD         0xFFFD
+#endif // !RC_INVOKED
+// TabView
+#define ID_WINDOW_TABFIRST              0xFF00 // = ATL_IDM_FIRST_MDICHILD
+#define ID_WINDOW_TABLAST               0xFFFD
+#define ID_WINDOW_SHOWTABLIST           0xFFFE
+
+// Help and App commands
+#define ID_APP_ABOUT                    0xE140
+#define ID_APP_EXIT                     0xE141
+#define ID_HELP_INDEX                   0xE142
+#define ID_HELP_FINDER                  0xE143
+#define ID_HELP_USING                   0xE144
+#define ID_CONTEXT_HELP                 0xE145      // shift-F1
+// special commands for processing help
+#define ID_HELP                         0xE146      // first attempt for F1
+#define ID_DEFAULT_HELP                 0xE147      // last attempt
+
+// Misc
+#define ID_NEXT_PANE                    0xE150
+#define ID_PREV_PANE                    0xE151
+#define ID_PANE_CLOSE                   0xE152
+
+// Format
+#define ID_FORMAT_FONT                  0xE160
+
+// Scroll
+#define ID_SCROLL_UP                    0xE170
+#define ID_SCROLL_DOWN                  0xE171
+#define ID_SCROLL_PAGE_UP               0xE172
+#define ID_SCROLL_PAGE_DOWN             0xE173
+#define ID_SCROLL_TOP                   0xE174
+#define ID_SCROLL_BOTTOM                0xE175
+#define ID_SCROLL_LEFT                  0xE176
+#define ID_SCROLL_RIGHT                 0xE177
+#define ID_SCROLL_PAGE_LEFT             0xE178
+#define ID_SCROLL_PAGE_RIGHT            0xE179
+#define ID_SCROLL_ALL_LEFT              0xE17A
+#define ID_SCROLL_ALL_RIGHT             0xE17B
+
+// OLE commands
+#define ID_OLE_INSERT_NEW               0xE200
+#define ID_OLE_EDIT_LINKS               0xE201
+#define ID_OLE_EDIT_CONVERT             0xE202
+#define ID_OLE_EDIT_CHANGE_ICON         0xE203
+#define ID_OLE_EDIT_PROPERTIES          0xE204
+#define ID_OLE_VERB_FIRST               0xE210     // range - 16 max
+#ifndef RC_INVOKED      // code only
+  #define ID_OLE_VERB_LAST              0xE21F
+#endif // !RC_INVOKED
+
+// View commands (same number used as IDW used for toolbar and status bar)
+#define ID_VIEW_TOOLBAR                 0xE800
+#define ID_VIEW_STATUS_BAR              0xE801
+#define ID_VIEW_REFRESH                 0xE803
+
+///////////////////////////////////////////////////////////////////////////////
+// Standard control IDs
+
+#ifdef IDC_STATIC
+  #undef IDC_STATIC
+#endif // IDC_STATIC
+#define IDC_STATIC              (-1)     // all static controls
+
+///////////////////////////////////////////////////////////////////////////////
+// Standard string error/warnings
+
+// idle status bar message
+#define ATL_IDS_IDLEMESSAGE             0xE001
+
+#ifndef RC_INVOKED      // code only
+  #define ATL_IDS_SCFIRST               0xEF00
+#endif // !RC_INVOKED
+
+#define ATL_IDS_SCSIZE                  0xEF00
+#define ATL_IDS_SCMOVE                  0xEF01
+#define ATL_IDS_SCMINIMIZE              0xEF02
+#define ATL_IDS_SCMAXIMIZE              0xEF03
+#define ATL_IDS_SCNEXTWINDOW            0xEF04
+#define ATL_IDS_SCPREVWINDOW            0xEF05
+#define ATL_IDS_SCCLOSE                 0xEF06
+#define ATL_IDS_SCRESTORE               0xEF12
+#define ATL_IDS_SCTASKLIST              0xEF13
+
+#define ATL_IDS_MDICHILD                0xEF1F
+#define ATL_IDS_MRU_FILE                0xEFDA
+
+///////////////////////////////////////////////////////////////////////////////
+// Misc. control IDs
+
+// Property Sheet control id's (determined with Spy++)
+#define ID_APPLY_NOW                    0x3021
+#define ID_WIZBACK                      0x3023
+#define ID_WIZNEXT                      0x3024
+#define ID_WIZFINISH                    0x3025
+#define ATL_IDC_TAB_CONTROL             0x3020
+
+#endif // __ATLRES_H__
diff --git a/include/WTL/Include/atlresce.h b/include/WTL/Include/atlresce.h
new file mode 100644 (file)
index 0000000..96211ee
--- /dev/null
@@ -0,0 +1,93 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLRESCE_H__
+#define __ATLRESCE_H__
+
+#pragma once
+
+#ifndef _WIN32_WCE
+       #error atlresCE.h is only for Windows CE
+#endif
+
+
+#ifdef RC_INVOKED
+#ifndef _INC_WINDOWS
+
+  #define VS_VERSION_INFO     1
+
+  #ifdef APSTUDIO_INVOKED
+    #define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols
+  #endif // APSTUDIO_INVOKED
+
+  #ifndef WINVER
+    #define WINVER 0x0400   // default to Windows Version 4.0
+  #endif // !WINVER
+
+  #if !defined(WCEOLE_ENABLE_DIALOGEX)
+    #define DIALOGEX DIALOG DISCARDABLE
+  #endif
+
+  #include <commctrl.h>
+  #define  SHMENUBAR RCDATA
+
+  #if defined(SHELLSDK_MODULES_AYGSHELL)
+    #include <aygshell.h> 
+  #else
+    #define NOMENU                 0xFFFF
+    #define IDS_SHNEW              1
+    #define IDM_SHAREDNEW          10
+    #define IDM_SHAREDNEWDEFAULT   11
+  #endif
+  #ifndef I_IMAGENONE
+       #define I_IMAGENONE            (-2)
+  #endif
+
+  #include <windows.h>
+
+#endif // !_INC_WINDOWS
+#endif // RC_INVOKED
+
+#include "atlres.h"
+
+#ifdef APSTUDIO_INVOKED
+       #undef APSTUDIO_HIDDEN_SYMBOLS
+#endif // APSTUDIO_INVOKED
+
+// Visual Studio dialog editor bug fix
+#ifndef DS_FIXEDSYS 
+       #define DS_FIXEDSYS 0
+#endif
+
+#define IDC_INFOSTATIC 0xFFFE   // == IDC_STATIC -1
+
+///////////////////////////////////////////////////////////////////////////////
+// Smartphone and PPC 2005 Resource IDs
+
+// Command and associated string resource IDs
+#define ID_MENU_OK                      0xE790
+#define ID_MENU_CANCEL                  0xE791
+#define ID_MENU                                                        0xE792
+#define ID_ACTION                                              0xE793
+#define ID_VIEW_FULLSCREEN              0xE802
+
+// MenuBar resource IDs
+#define ATL_IDM_MENU_DONE               0xE701
+#define ATL_IDM_MENU_CANCEL             0xE702
+#define ATL_IDM_MENU_DONECANCEL         0xE703
+
+// Default device MenuBar control ID and MenuBar resource ID
+#define ATL_IDW_MENU_BAR                               0xE802  
+
+// SmartPhone spinned controls ID offset for CSpinCtrl
+#define ATL_IDW_SPIN_ID                 9999
+
+#endif // __ATLRESCE_H__
diff --git a/include/WTL/Include/atlscrl.h b/include/WTL/Include/atlscrl.h
new file mode 100644 (file)
index 0000000..e98451e
--- /dev/null
@@ -0,0 +1,2015 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLSCRL_H__
+#define __ATLSCRL_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlscrl.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atlscrl.h requires atlwin.h to be included first
+#endif
+
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+  #include <zmouse.h>
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+
+#ifndef GET_WHEEL_DELTA_WPARAM
+  #define GET_WHEEL_DELTA_WPARAM(wParam)  ((short)HIWORD(wParam))
+#endif
+
+#ifndef WM_MOUSEHWHEEL
+  #define WM_MOUSEHWHEEL                  0x020E
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CScrollImpl<T>
+// CScrollWindowImpl<T, TBase, TWinTraits>
+// CMapScrollImpl<T>
+// CMapScrollWindowImpl<T, TBase, TWinTraits>
+// CFSBWindowT<TBase>
+// CZoomScrollImpl<T>
+// CZoomScrollWindowImpl<T, TBase, TWinTraits>
+// CScrollContainerImpl<T, TBase, TWinTraits>
+// CScrollContainer
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CScrollImpl - Provides scrolling support to any window
+
+// Scroll extended styles
+#define SCRL_SCROLLCHILDREN    0x00000001
+#define SCRL_ERASEBACKGROUND   0x00000002
+#define SCRL_NOTHUMBTRACKING   0x00000004
+#if (WINVER >= 0x0500)
+#define SCRL_SMOOTHSCROLL      0x00000008
+#endif // (WINVER >= 0x0500)
+#define SCRL_DISABLENOSCROLLV  0x00000010
+#define SCRL_DISABLENOSCROLLH  0x00000020
+#define SCRL_DISABLENOSCROLL   (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH)
+
+
+template <class T>
+class CScrollImpl
+{
+public:
+       enum { uSCROLL_FLAGS = SW_INVALIDATE };
+
+       POINT m_ptOffset;
+       SIZE m_sizeAll;
+       SIZE m_sizeLine;
+       SIZE m_sizePage;
+       SIZE m_sizeClient;
+       int m_zDelta;              // current wheel value
+       int m_nWheelLines;         // number of lines to scroll on wheel
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+       // Note that this message must be forwarded from a top level window
+       UINT m_uMsgMouseWheel;     // MSH_MOUSEWHEEL
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+       int m_zHDelta;              // current horizontal wheel value
+       int m_nHWheelChars;         // number of chars to scroll on horizontal wheel
+       UINT m_uScrollFlags;
+       DWORD m_dwExtendedStyle;   // scroll specific extended styles
+
+// Constructor
+       CScrollImpl() : m_zDelta(0), m_nWheelLines(3), 
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+                       m_uMsgMouseWheel(0U), 
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+                       m_zHDelta(0), m_nHWheelChars(3), 
+                       m_uScrollFlags(0U), m_dwExtendedStyle(0)
+       {
+               m_ptOffset.x = 0;
+               m_ptOffset.y = 0;
+               m_sizeAll.cx = 0;
+               m_sizeAll.cy = 0;
+               m_sizePage.cx = 0;
+               m_sizePage.cy = 0;
+               m_sizeLine.cx = 0;
+               m_sizeLine.cy = 0;
+               m_sizeClient.cx = 0;
+               m_sizeClient.cy = 0;
+
+               SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND);
+       }
+
+// Attributes & Operations
+       DWORD GetScrollExtendedStyle() const
+       {
+               return m_dwExtendedStyle;
+       }
+
+       DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
+       {
+               DWORD dwPrevStyle = m_dwExtendedStyle;
+               if(dwMask == 0)
+                       m_dwExtendedStyle = dwExtendedStyle;
+               else
+                       m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
+               // cache scroll flags
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+               m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0);
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+               m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0);
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+               return dwPrevStyle;
+       }
+
+       // offset operations
+       void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               pT->AdjustScrollOffset(x, y);
+
+               int dx = m_ptOffset.x - x;
+               int dy = m_ptOffset.y - y;
+               m_ptOffset.x = x;
+               m_ptOffset.y = y;
+
+               // block: set horizontal scroll bar
+               {
+                       SCROLLINFO si = { sizeof(SCROLLINFO) };
+                       si.fMask = SIF_POS;
+                       if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
+                               si.fMask |= SIF_DISABLENOSCROLL;
+                       si.nPos = m_ptOffset.x;
+                       pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
+               }
+
+               // block: set vertical scroll bar
+               {
+                       SCROLLINFO si = { sizeof(SCROLLINFO) };
+                       si.fMask = SIF_POS;
+                       if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
+                               si.fMask |= SIF_DISABLENOSCROLL;
+                       si.nPos = m_ptOffset.y;
+                       pT->SetScrollInfo(SB_VERT, &si, bRedraw);
+               }
+
+               // Move all children if needed
+               if(IsScrollingChildren() && (dx != 0 || dy != 0))
+               {
+                       for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
+                       {
+                               RECT rect = { 0 };
+                               ::GetWindowRect(hWndChild, &rect);
+                               ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
+                               ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+                       }
+               }
+
+               if(bRedraw)
+                       pT->Invalidate();
+       }
+
+       void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
+       {
+               SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
+       }
+
+       void GetScrollOffset(POINT& ptOffset) const
+       {
+               ptOffset = m_ptOffset;
+       }
+
+       // size operations
+       void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               m_sizeAll.cx = cx;
+               m_sizeAll.cy = cy;
+
+               int x = 0;
+               int y = 0;
+               if(!bResetOffset)
+               {
+                       x = m_ptOffset.x;
+                       y = m_ptOffset.y;
+                       pT->AdjustScrollOffset(x, y);
+               }
+
+               int dx = m_ptOffset.x - x;
+               int dy = m_ptOffset.y - y;
+               m_ptOffset.x = x;
+               m_ptOffset.y = y;
+
+               // block: set horizontal scroll bar
+               {
+                       SCROLLINFO si = { sizeof(SCROLLINFO) };
+                       si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
+                       if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
+                               si.fMask |= SIF_DISABLENOSCROLL;
+                       si.nMin = 0;
+                       si.nMax = m_sizeAll.cx - 1;
+                       si.nPage = m_sizeClient.cx;
+                       si.nPos = m_ptOffset.x;
+                       pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
+               }
+
+               // block: set vertical scroll bar
+               {
+                       SCROLLINFO si = { sizeof(SCROLLINFO) };
+                       si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
+                       if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
+                               si.fMask |= SIF_DISABLENOSCROLL;
+                       si.nMin = 0;
+                       si.nMax = m_sizeAll.cy - 1;
+                       si.nPage = m_sizeClient.cy;
+                       si.nPos = m_ptOffset.y;
+                       pT->SetScrollInfo(SB_VERT, &si, bRedraw);
+               }
+
+               // Move all children if needed
+               if(IsScrollingChildren() && (dx != 0 || dy != 0))
+               {
+                       for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
+                       {
+                               RECT rect = { 0 };
+                               ::GetWindowRect(hWndChild, &rect);
+                               ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
+                               ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+                       }
+               }
+
+               SetScrollLine(0, 0);
+               SetScrollPage(0, 0);
+
+               if(bRedraw)
+                       pT->Invalidate();
+       }
+
+       void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
+       {
+               SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset);
+       }
+
+       void GetScrollSize(SIZE& sizeWnd) const
+       {
+               sizeWnd = m_sizeAll;
+       }
+
+       // line operations
+       void SetScrollLine(int cxLine, int cyLine)
+       {
+               ATLASSERT(cxLine >= 0 && cyLine >= 0);
+               ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
+
+               m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100);
+               m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100);
+       }
+
+       void SetScrollLine(SIZE sizeLine)
+       {
+               SetScrollLine(sizeLine.cx, sizeLine.cy);
+       }
+
+       void GetScrollLine(SIZE& sizeLine) const
+       {
+               sizeLine = m_sizeLine;
+       }
+
+       // page operations
+       void SetScrollPage(int cxPage, int cyPage)
+       {
+               ATLASSERT(cxPage >= 0 && cyPage >= 0);
+               ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
+
+               m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10);
+               m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10);
+       }
+
+       void SetScrollPage(SIZE sizePage)
+       {
+               SetScrollPage(sizePage.cx, sizePage.cy);
+       }
+
+       void GetScrollPage(SIZE& sizePage) const
+       {
+               sizePage = m_sizePage;
+       }
+
+       // commands
+       void ScrollLineDown()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
+       }
+
+       void ScrollLineUp()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
+       }
+
+       void ScrollPageDown()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
+       }
+
+       void ScrollPageUp()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
+       }
+
+       void ScrollTop()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
+       }
+
+       void ScrollBottom()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
+       }
+
+       void ScrollLineRight()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+       }
+
+       void ScrollLineLeft()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+       }
+
+       void ScrollPageRight()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+       }
+
+       void ScrollPageLeft()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+       }
+
+       void ScrollAllLeft()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+       }
+
+       void ScrollAllRight()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+       }
+
+       // scroll to make point/view/window visible
+       void ScrollToView(POINT pt)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               RECT rect = { pt.x, pt.y, pt.x, pt.y };
+               pT->ScrollToView(rect);
+       }
+
+       void ScrollToView(RECT& rect)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               RECT rcClient = { 0 };
+               pT->GetClientRect(&rcClient);
+
+               int x = m_ptOffset.x;
+               if(rect.left < m_ptOffset.x)
+                       x = rect.left;
+               else if(rect.right > (m_ptOffset.x + rcClient.right))
+                       x = rect.right - rcClient.right;
+
+               int y = m_ptOffset.y;
+               if(rect.top < m_ptOffset.y)
+                       y = rect.top;
+               else if(rect.bottom > (m_ptOffset.y + rcClient.bottom))
+                       y = rect.bottom - rcClient.bottom;
+
+               SetScrollOffset(x, y);
+       }
+
+       void ScrollToView(HWND hWnd)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               RECT rect = { 0 };
+               ::GetWindowRect(hWnd, &rect);
+               ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
+               ScrollToView(rect);
+       }
+
+       BEGIN_MSG_MAP(CScrollImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
+               MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
+               MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+               MESSAGE_HANDLER(m_uMsgMouseWheel, OnMouseWheel)
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+               MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+#endif // !_WIN32_WCE
+       // standard scroll commands
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop)
+               COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom)
+               COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               GetSystemSettings();
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
+               return 0;
+       }
+
+       LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+               return 0;
+       }
+
+       LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE)
+               uMsg;
+               int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
+#else
+               int zDelta = (uMsg == WM_MOUSEWHEEL) ? (int)GET_WHEEL_DELTA_WPARAM(wParam) : (int)wParam;
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE))
+               int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN);
+               m_zDelta += zDelta;   // cumulative
+               int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines;
+               if(m_sizeAll.cy > m_sizeClient.cy)
+               {
+                       for(int i = 0; i < zTotal; i += WHEEL_DELTA)
+                       {
+                               pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
+                               pT->UpdateWindow();
+                       }
+               }
+               else            // can't scroll vertically, scroll horizontally
+               {
+                       for(int i = 0; i < zTotal; i += WHEEL_DELTA)
+                       {
+                               pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+                               pT->UpdateWindow();
+                       }
+               }
+               m_zDelta %= WHEEL_DELTA;
+
+               return 0;
+       }
+
+       LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
+               int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT);
+               m_zHDelta += zDelta;   // cumulative
+               int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars;
+               if(m_sizeAll.cx > m_sizeClient.cx)
+               {
+                       for(int i = 0; i < zTotal; i += WHEEL_DELTA)
+                       {
+                               pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
+                               pT->UpdateWindow();
+                       }
+               }
+               m_zHDelta %= WHEEL_DELTA;
+
+               return 0;
+       }
+
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               GetSystemSettings();
+               return 0;
+       }
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               m_sizeClient.cx = GET_X_LPARAM(lParam);
+               m_sizeClient.cy = GET_Y_LPARAM(lParam);
+
+               // block: set horizontal scroll bar
+               {
+                       SCROLLINFO si = { sizeof(SCROLLINFO) };
+                       si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
+                       si.nMin = 0;
+                       si.nMax = m_sizeAll.cx - 1;
+                       if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
+                               si.fMask |= SIF_DISABLENOSCROLL;
+                       si.nPage = m_sizeClient.cx;
+                       si.nPos = m_ptOffset.x;
+                       pT->SetScrollInfo(SB_HORZ, &si, TRUE);
+               }
+
+               // block: set vertical scroll bar
+               {
+                       SCROLLINFO si = { sizeof(SCROLLINFO) };
+                       si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
+                       si.nMin = 0;
+                       si.nMax = m_sizeAll.cy - 1;
+                       if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
+                               si.fMask |= SIF_DISABLENOSCROLL;
+                       si.nPage = m_sizeClient.cy;
+                       si.nPos = m_ptOffset.y;
+                       pT->SetScrollInfo(SB_VERT, &si, TRUE);
+               }
+
+               int x = m_ptOffset.x;
+               int y = m_ptOffset.y;
+               if(pT->AdjustScrollOffset(x, y))
+               {
+                       // Children will be moved in SetScrollOffset, if needed
+                       pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN));
+                       SetScrollOffset(x, y, FALSE);
+               }
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               if(wParam != NULL)
+               {
+                       CDCHandle dc = (HDC)wParam;
+                       POINT ptViewportOrg = { 0, 0 };
+                       dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
+                       pT->DoPaint(dc);
+                       dc.SetViewportOrg(ptViewportOrg);
+               }
+               else
+               {
+                       CPaintDC dc(pT->m_hWnd);
+                       dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
+                       pT->DoPaint(dc.m_hDC);
+               }
+               return 0;
+       }
+
+       // scrolling handlers
+       LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollLineUp();
+               return 0;
+       }
+
+       LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollLineDown();
+               return 0;
+       }
+
+       LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollPageUp();
+               return 0;
+       }
+
+       LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollPageDown();
+               return 0;
+       }
+
+       LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollTop();
+               return 0;
+       }
+
+       LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollBottom();
+               return 0;
+       }
+
+       LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollLineLeft();
+               return 0;
+       }
+
+       LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollLineRight();
+               return 0;
+       }
+
+       LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollPageLeft();
+               return 0;
+       }
+
+       LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollPageRight();
+               return 0;
+       }
+
+       LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollAllLeft();
+               return 0;
+       }
+
+       LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ScrollAllRight();
+               return 0;
+       }
+
+// Overrideables
+       void DoPaint(CDCHandle /*dc*/)
+       {
+               // must be implemented in a derived class
+               ATLASSERT(FALSE);
+       }
+
+// Implementation
+       void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine)
+       {
+               T* pT = static_cast<T*>(this);
+               RECT rect = { 0 };
+               pT->GetClientRect(&rect);
+               int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right;
+               int cxyMax = cxySizeAll - cxyClient;
+
+               if(cxyMax < 0)   // can't scroll, client area is bigger
+                       return;
+
+               bool bUpdate = true;
+               int cxyScroll = 0;
+
+               switch(nScrollCode)
+               {
+               case SB_TOP:            // top or all left
+                       cxyScroll = cxyOffset;
+                       cxyOffset = 0;
+                       break;
+               case SB_BOTTOM:         // bottom or all right
+                       cxyScroll = cxyOffset - cxyMax;
+                       cxyOffset = cxyMax;
+                       break;
+               case SB_LINEUP:         // line up or line left
+                       if(cxyOffset >= cxySizeLine)
+                       {
+                               cxyScroll = cxySizeLine;
+                               cxyOffset -= cxySizeLine;
+                       }
+                       else
+                       {
+                               cxyScroll = cxyOffset;
+                               cxyOffset = 0;
+                       }
+                       break;
+               case SB_LINEDOWN:       // line down or line right
+                       if(cxyOffset < cxyMax - cxySizeLine)
+                       {
+                               cxyScroll = -cxySizeLine;
+                               cxyOffset += cxySizeLine;
+                       }
+                       else
+                       {
+                               cxyScroll = cxyOffset - cxyMax;
+                               cxyOffset = cxyMax;
+                       }
+                       break;
+               case SB_PAGEUP:         // page up or page left
+                       if(cxyOffset >= cxySizePage)
+                       {
+                               cxyScroll = cxySizePage;
+                               cxyOffset -= cxySizePage;
+                       }
+                       else
+                       {
+                               cxyScroll = cxyOffset;
+                               cxyOffset = 0;
+                       }
+                       break;
+               case SB_PAGEDOWN:       // page down or page right
+                       if(cxyOffset < cxyMax - cxySizePage)
+                       {
+                               cxyScroll = -cxySizePage;
+                               cxyOffset += cxySizePage;
+                       }
+                       else
+                       {
+                               cxyScroll = cxyOffset - cxyMax;
+                               cxyOffset = cxyMax;
+                       }
+                       break;
+               case SB_THUMBTRACK:
+                       if(IsNoThumbTracking())
+                               break;
+                       // else fall through
+               case SB_THUMBPOSITION:
+                       {
+                               SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS };
+                               if(pT->GetScrollInfo(nType, &si))
+                               {
+                                       cxyScroll = cxyOffset - si.nTrackPos;
+                                       cxyOffset = si.nTrackPos;
+                               }
+                       }
+                       break;
+               case SB_ENDSCROLL:
+               default:
+                       bUpdate = false;
+                       break;
+               }
+
+               if(bUpdate && cxyScroll != 0)
+               {
+                       pT->SetScrollPos(nType, cxyOffset, TRUE);
+                       if(nType == SB_VERT)
+                               pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags);
+                       else
+                               pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags);
+               }
+       }
+
+       static int CalcLineOrPage(int nVal, int nMax, int nDiv)
+       {
+               if(nVal == 0)
+               {
+                       nVal = nMax / nDiv;
+                       if(nVal < 1)
+                               nVal = 1;
+               }
+               else if(nVal > nMax)
+               {
+                       nVal = nMax;
+               }
+
+               return nVal;
+       }
+
+       bool AdjustScrollOffset(int& x, int& y)
+       {
+               int xOld = x;
+               int yOld = y;
+
+               int cxMax = m_sizeAll.cx - m_sizeClient.cx;
+               if(x > cxMax)
+                       x = (cxMax >= 0) ? cxMax : 0;
+               else if(x < 0)
+                       x = 0;
+
+               int cyMax = m_sizeAll.cy - m_sizeClient.cy;
+               if(y > cyMax)
+                       y = (cyMax >= 0) ? cyMax : 0;
+               else if(y < 0)
+                       y = 0;
+
+               return (x != xOld || y != yOld);
+       }
+
+       void GetSystemSettings()
+       {
+#ifndef _WIN32_WCE
+#ifndef SPI_GETWHEELSCROLLLINES
+               const UINT SPI_GETWHEELSCROLLLINES = 104;
+#endif // !SPI_GETWHEELSCROLLLINES
+               ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0);
+
+#ifndef SPI_GETWHEELSCROLLCHARS
+               const UINT SPI_GETWHEELSCROLLCHARS = 0x006C;
+#endif // !SPI_GETWHEELSCROLLCHARS
+               ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0);
+
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               if(m_uMsgMouseWheel != 0)
+                       m_uMsgMouseWheel = ::RegisterWindowMessage(MSH_MOUSEWHEEL);
+
+               HWND hWndWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE);
+               if(::IsWindow(hWndWheel))
+               {
+                       UINT uMsgScrollLines = ::RegisterWindowMessage(MSH_SCROLL_LINES);
+                       if(uMsgScrollLines != 0)
+                               m_nWheelLines = (int)::SendMessage(hWndWheel, uMsgScrollLines, 0, 0L);
+               }
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+#endif // !_WIN32_WCE
+       }
+
+       bool IsScrollingChildren() const
+       {
+               return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0;
+       }
+
+       bool IsErasingBackground() const
+       {
+               return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0;
+       }
+
+       bool IsNoThumbTracking() const
+       {
+               return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0;
+       }
+
+#if (WINVER >= 0x0500)
+       bool IsSmoothScroll() const
+       {
+               return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0;
+       }
+#endif // (WINVER >= 0x0500)
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CScrollWindowImpl - Implements a scrollable window
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CScrollImpl< T >
+{
+public:
+       BEGIN_MSG_MAP(CScrollWindowImpl)
+               MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
+               MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
+               MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+               MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
+               MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
+               MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
+               MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint)
+#endif // !_WIN32_WCE
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
+               COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
+               COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
+       END_MSG_MAP()
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMapScrollImpl - Provides mapping and scrolling support to any window
+
+#ifndef _WIN32_WCE
+
+template <class T>
+class CMapScrollImpl : public CScrollImpl< T >
+{
+public:
+       int m_nMapMode;
+       RECT m_rectLogAll;
+       SIZE m_sizeLogLine;
+       SIZE m_sizeLogPage;
+
+// Constructor
+       CMapScrollImpl() : m_nMapMode(MM_TEXT)
+       {
+               ::SetRectEmpty(&m_rectLogAll);
+               m_sizeLogPage.cx = 0;
+               m_sizeLogPage.cy = 0;
+               m_sizeLogLine.cx = 0;
+               m_sizeLogLine.cy = 0;
+       }
+
+// Attributes & Operations
+       // mapping mode operations
+       void SetScrollMapMode(int nMapMode)
+       {
+               ATLASSERT(nMapMode >= MM_MIN && nMapMode <= MM_MAX_FIXEDSCALE);
+               m_nMapMode = nMapMode;
+       }
+
+       int GetScrollMapMode() const
+       {
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+               return m_nMapMode;
+       }
+
+       // offset operations
+       void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+               POINT ptOff = { x, y };
+               // block: convert logical to device units
+               {
+                       CWindowDC dc(NULL);
+                       dc.SetMapMode(m_nMapMode);
+                       dc.LPtoDP(&ptOff);
+               }
+               CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw);
+       }
+
+       void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
+       {
+               SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
+       }
+
+       void GetScrollOffset(POINT& ptOffset) const
+       {
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+               ptOffset = m_ptOffset;
+               // block: convert device to logical units
+               {
+                       CWindowDC dc(NULL);
+                       dc.SetMapMode(m_nMapMode);
+                       dc.DPtoLP(&ptOffset);
+               }
+       }
+
+       // size operations
+       void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true)
+       {
+               ATLASSERT(xMax > xMin && yMax > yMin);
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+
+               ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax);
+
+               SIZE sizeAll = { 0 };
+               sizeAll.cx = xMax - xMin + 1;
+               sizeAll.cy = yMax - yMin + 1;
+               // block: convert logical to device units
+               {
+                       CWindowDC dc(NULL);
+                       dc.SetMapMode(m_nMapMode);
+                       dc.LPtoDP(&sizeAll);
+               }
+               CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
+               SetScrollLine(0, 0);
+               SetScrollPage(0, 0);
+       }
+
+       void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true)
+       {
+               SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset);
+       }
+
+       void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
+       {
+               SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset);
+       }
+
+       void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
+       {
+               SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset);
+       }
+
+       void GetScrollSize(RECT& rcScroll) const
+       {
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+               rcScroll = m_rectLogAll;
+       }
+
+       // line operations
+       void SetScrollLine(int cxLine, int cyLine)
+       {
+               ATLASSERT(cxLine >= 0 && cyLine >= 0);
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+
+               m_sizeLogLine.cx = cxLine;
+               m_sizeLogLine.cy = cyLine;
+               SIZE sizeLine = m_sizeLogLine;
+               // block: convert logical to device units
+               {
+                       CWindowDC dc(NULL);
+                       dc.SetMapMode(m_nMapMode);
+                       dc.LPtoDP(&sizeLine);
+               }
+               CScrollImpl< T >::SetScrollLine(sizeLine);
+       }
+
+       void SetScrollLine(SIZE sizeLine)
+       {
+               SetScrollLine(sizeLine.cx, sizeLine.cy);
+       }
+
+       void GetScrollLine(SIZE& sizeLine) const
+       {
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+               sizeLine = m_sizeLogLine;
+       }
+
+       // page operations
+       void SetScrollPage(int cxPage, int cyPage)
+       {
+               ATLASSERT(cxPage >= 0 && cyPage >= 0);
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+
+               m_sizeLogPage.cx = cxPage;
+               m_sizeLogPage.cy = cyPage;
+               SIZE sizePage = m_sizeLogPage;
+               // block: convert logical to device units
+               {
+                       CWindowDC dc(NULL);
+                       dc.SetMapMode(m_nMapMode);
+                       dc.LPtoDP(&sizePage);
+               }
+               CScrollImpl< T >::SetScrollPage(sizePage);
+       }
+
+       void SetScrollPage(SIZE sizePage)
+       {
+               SetScrollPage(sizePage.cx, sizePage.cy);
+       }
+
+       void GetScrollPage(SIZE& sizePage) const
+       {
+               ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
+               sizePage = m_sizeLogPage;
+       }
+
+       BEGIN_MSG_MAP(CMapScrollImpl)
+               MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
+               MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
+               MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
+               MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
+               COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
+               COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
+       END_MSG_MAP()
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               if(wParam != NULL)
+               {
+                       CDCHandle dc = (HDC)wParam;
+                       int nMapModeSav = dc.GetMapMode();
+                       dc.SetMapMode(m_nMapMode);
+                       POINT ptViewportOrg = { 0, 0 };
+                       if(m_nMapMode == MM_TEXT)
+                               dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
+                       else
+                               dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy, &ptViewportOrg);
+                       POINT ptWindowOrg = { 0, 0 };
+                       dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg);
+
+                       pT->DoPaint(dc);
+
+                       dc.SetMapMode(nMapModeSav);
+                       dc.SetViewportOrg(ptViewportOrg);
+                       dc.SetWindowOrg(ptWindowOrg);
+               }
+               else
+               {
+                       CPaintDC dc(pT->m_hWnd);
+                       dc.SetMapMode(m_nMapMode);
+                       if(m_nMapMode == MM_TEXT)
+                               dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
+                       else
+                               dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy);
+                       dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top);
+                       pT->DoPaint(dc.m_hDC);
+               }
+               return 0;
+       }
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMapScrollWindowImpl - Implements scrolling window with mapping
+
+#ifndef _WIN32_WCE
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T >
+{
+public:
+       BEGIN_MSG_MAP(CMapScrollWindowImpl)
+               MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
+               MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
+               MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
+               MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
+               MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint)
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
+               COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
+               COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
+       END_MSG_MAP()
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support
+
+#if defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+template <class TBase = ATL::CWindow>
+class CFSBWindowT : public TBase, public CFlatScrollBarImpl<CFSBWindowT< TBase > >
+{
+public:
+// Constructors
+       CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CFSBWindowT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+// CWindow overrides that use flat scroll bar API
+// (only those methods that are used by scroll window classes)
+       int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return FlatSB_SetScrollPos(nBar, nPos, bRedraw);
+       }
+
+       BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return FlatSB_GetScrollInfo(nBar, lpScrollInfo);
+       }
+
+       BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw);
+       }
+};
+
+typedef CFSBWindowT<ATL::CWindow>   CFSBWindow;
+
+#endif // defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CZoomScrollImpl - Provides zooming and scrolling support to any window
+
+#ifndef _WIN32_WCE
+
+// The zoom modes that can be set with the SetZoomMode method
+enum
+{
+       ZOOMMODE_OFF, 
+       ZOOMMODE_IN,   // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged.
+       ZOOMMODE_OUT   // If left mouse button clicked, zoom out on point clicked.
+};
+
+// Notification to parent that zoom scale changed as a result of user mouse action.
+#define ZSN_ZOOMCHANGED        (NM_FIRST - 50) 
+
+template <class T>
+class CZoomScrollImpl : public CScrollImpl< T >
+{
+public:
+       enum { m_cxyMinZoomRect = 12 };   // min rect size to zoom in on rect.
+
+// Data members
+       SIZE m_sizeLogAll;              
+       SIZE m_sizeLogLine;     
+       SIZE m_sizeLogPage;
+       float m_fZoomScale;
+       float m_fZoomScaleMin;
+       float m_fZoomDelta;   // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click.
+       int m_nZoomMode;                
+       RECT m_rcTrack;
+       bool m_bTracking;
+
+// Constructor
+       CZoomScrollImpl():
+                       m_fZoomScale(1.0),
+                       m_fZoomScaleMin(0.5),
+                       m_fZoomDelta(0.5),
+                       m_nZoomMode(ZOOMMODE_OFF),
+                       m_bTracking(false)
+       {
+               m_sizeLogAll.cx = 0;
+               m_sizeLogAll.cy = 0;
+               m_sizeLogPage.cx = 0;
+               m_sizeLogPage.cy = 0;
+               m_sizeLogLine.cx = 0;
+               m_sizeLogLine.cy = 0;
+               ::SetRectEmpty(&m_rcTrack);
+       }
+
+// Attributes & Operations
+
+       // size operations
+       void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
+       {
+               ATLASSERT(cxLog >= 0 && cyLog >= 0);
+
+               // Set up the defaults
+               if (cxLog == 0 && cyLog == 0)
+               {
+                       cxLog = 1;
+                       cyLog = 1;
+               }
+
+               m_sizeLogAll.cx = cxLog;
+               m_sizeLogAll.cy = cyLog;
+               SIZE sizeAll = { 0 };
+               sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale);
+               sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale);
+
+               CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
+       }
+
+       void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
+       {
+               SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset);
+       }
+
+       void GetScrollSize(SIZE& sizeLog) const
+       {
+               sizeLog = m_sizeLogAll;
+       }
+
+       // line operations
+       void SetScrollLine(int cxLogLine, int cyLogLine)
+       {
+               ATLASSERT(cxLogLine >= 0 && cyLogLine >= 0);
+
+               m_sizeLogLine.cx = cxLogLine;
+               m_sizeLogLine.cy = cyLogLine;
+
+               SIZE sizeLine = { 0 };
+               sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale);
+               sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale);
+               CScrollImpl< T >::SetScrollLine(sizeLine);
+       }
+
+       void SetScrollLine(SIZE sizeLogLine)
+       {
+               SetScrollLine(sizeLogLine.cx, sizeLogLine.cy);
+       }
+
+       void GetScrollLine(SIZE& sizeLogLine) const
+       {
+               sizeLogLine = m_sizeLogLine;
+       }
+
+       // page operations
+       void SetScrollPage(int cxLogPage, int cyLogPage)
+       {
+               ATLASSERT(cxLogPage >= 0 && cyLogPage >= 0);
+
+               m_sizeLogPage.cx = cxLogPage;
+               m_sizeLogPage.cy = cyLogPage;
+
+               SIZE sizePage = { 0 };
+               sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale);
+               sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale);
+
+               CScrollImpl< T >::SetScrollPage(sizePage);
+       }
+
+       void SetScrollPage(SIZE sizeLogPage)
+       {
+               SetScrollPage(sizeLogPage.cx, sizeLogPage.cy);
+       }
+
+       void GetScrollPage(SIZE& sizeLogPage) const
+       {
+               sizeLogPage = m_sizeLogPage;
+       }
+
+       void SetZoomScale(float fZoomScale)
+       {
+               ATLASSERT(fZoomScale > 0);
+
+               if(fZoomScale > 0 && fZoomScale >= m_fZoomScaleMin)
+                       m_fZoomScale = fZoomScale;
+       }
+
+       float GetZoomScale() const
+       {
+               return m_fZoomScale;
+       }
+
+       void SetZoomScaleMin(float fZoomScaleMin)
+       {
+               m_fZoomScaleMin = fZoomScaleMin;
+       }
+
+       float GetZoomScaleMin() const
+       {
+               return m_fZoomScaleMin;
+       }
+
+       void SetZoomDelta(float fZoomDelta)
+       {
+               ATLASSERT(fZoomDelta >= 0);
+
+               if(fZoomDelta >= 0)
+                       m_fZoomDelta = fZoomDelta;
+       }
+
+       float GetZoomDelta() const
+       {
+               return m_fZoomDelta;
+       }
+
+       void SetZoomMode(int nZoomMode)
+       {
+               m_nZoomMode = nZoomMode;
+       }
+
+       int GetZoomMode() const
+       {
+               return m_nZoomMode;
+       }
+
+       void Zoom(int x, int y, float fZoomScale)
+       {
+               if(fZoomScale <= 0)
+                       return;
+
+               fZoomScale = max(fZoomScale, m_fZoomScaleMin);
+
+               T* pT = static_cast<T*>(this);
+               POINT pt = { x, y };
+               if(!pT->PtInDevRect(pt))
+                       return;
+
+               pT->ViewDPtoLP(&pt);
+               pT->Zoom(fZoomScale, false);
+               pT->CenterOnLogicalPoint(pt);
+       }
+
+       void Zoom(POINT pt, float fZoomScale)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->Zoom(pt.x, pt.y, fZoomScale);
+       }
+
+       void Zoom(RECT& rc)
+       {
+               T* pT = static_cast<T*>(this);
+               RECT rcZoom = rc;
+               pT->NormalizeRect(rcZoom);
+               SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top };
+               POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 };
+               if(size.cx < m_cxyMinZoomRect || size.cy < m_cxyMinZoomRect)
+               {
+                       pT->Zoom(pt, m_fZoomScale + m_fZoomDelta);
+                       return;
+               }
+
+               ATLASSERT(size.cx > 0 && size.cy > 0);
+               
+               float fScaleH = (float)(m_sizeClient.cx  + 1) / (float)size.cx;
+               float fScaleV = (float)(m_sizeClient.cy + 1) / (float)size.cy;
+               float fZoomScale = min(fScaleH, fScaleV) * m_fZoomScale;
+               pT->Zoom(pt, fZoomScale);               
+       }
+
+       void Zoom(float fZoomScale, bool bCenter = true)
+       {
+               if(fZoomScale <= 0)
+                       return;
+
+               fZoomScale = max(fZoomScale, m_fZoomScaleMin);
+
+
+               T* pT = static_cast<T*>(this);
+               POINT pt = { 0 };
+               if(bCenter)
+               {
+                       RECT rc;
+                       ::GetClientRect(pT->m_hWnd, &rc);
+                       pt.x = rc.right / 2;
+                       pt.y = rc.bottom / 2;
+                       pT->ViewDPtoLP(&pt);
+               }
+
+               // Modify the Viewport extent
+               m_fZoomScale = fZoomScale;
+               SIZE sizeAll = { 0 };
+               sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale);
+               sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale);
+               
+               // Update scroll bars and window
+               CScrollImpl< T >::SetScrollSize(sizeAll);
+
+               if(bCenter)
+                       pT->CenterOnLogicalPoint(pt);
+       }
+
+       // Helper functions
+       void PrepareDC(CDCHandle dc)
+       {
+               ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
+               dc.SetMapMode(MM_ANISOTROPIC);
+               dc.SetWindowExt(m_sizeLogAll);
+               dc.SetViewportExt(m_sizeAll);
+               dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
+       }
+
+       void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1)
+       {
+               ATLASSERT(lpPoints);
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+
+               CWindowDC dc(pT->m_hWnd);
+               pT->PrepareDC(dc.m_hDC);
+               dc.DPtoLP(lpPoints, nCount);
+       }
+
+       void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1)
+       {
+               ATLASSERT(lpPoints);
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+       
+               CWindowDC dc(pT->m_hWnd);
+               pT->PrepareDC(dc.m_hDC);
+               dc.LPtoDP(lpPoints, nCount);
+       }
+
+       void ClientToDevice(POINT &pt)
+       {
+               pt.x += m_ptOffset.x;
+               pt.y += m_ptOffset.y;
+       }        
+
+       void DeviceToClient(POINT &pt)
+       {
+               pt.x -= m_ptOffset.x;
+               pt.y -= m_ptOffset.y;
+       }
+
+       void CenterOnPoint(POINT pt)
+       {
+               T* pT = static_cast<T*>(this);
+               RECT rect;
+               pT->GetClientRect(&rect);
+
+               int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x;
+               if(xOfs < 0)
+               {
+                       xOfs = 0;
+               }
+               else 
+               {
+                       int xMax = max((int)(m_sizeAll.cx - rect.right), 0);
+                       if(xOfs > xMax)
+                               xOfs = xMax;
+               }
+               
+               int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y;
+               if(yOfs < 0)
+               {
+                       yOfs = 0;
+               }
+               else 
+               {
+                       int yMax = max((int)(m_sizeAll.cy - rect.bottom), 0);
+                       if(yOfs > yMax)
+                               yOfs = yMax;
+               }
+
+               CScrollImpl< T >::SetScrollOffset(xOfs, yOfs);
+       }
+
+       void CenterOnLogicalPoint(POINT ptLog)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->ViewLPtoDP(&ptLog);
+               pT->DeviceToClient(ptLog);
+               pT->CenterOnPoint(ptLog);
+       }
+
+       BOOL PtInDevRect(POINT pt)
+       {
+               RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy };
+               ::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y);
+               return ::PtInRect(&rc, pt);
+       }
+
+       void NormalizeRect(RECT& rc)
+       {
+               if(rc.left > rc.right) 
+               {
+                       int r = rc.right;
+                       rc.right = rc.left;
+                       rc.left = r;
+               }
+               if(rc.top > rc.bottom)
+               {
+                       int b = rc.bottom;
+                       rc.bottom = rc.top;
+                       rc.top = b;
+               }
+       }
+
+       void DrawTrackRect()
+       {
+               T* pT = static_cast<T*>(this);
+               const SIZE sizeLines = { 2, 2 };
+               RECT rc = m_rcTrack;
+               pT->NormalizeRect(rc);
+               if(!::IsRectEmpty(&rc))
+               {
+                       ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2);
+                       CWindowDC dc(NULL);
+                       dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines);
+               }
+       }
+
+       void NotifyParentZoomChanged()
+       {
+               T* pT = static_cast<T*>(this);
+               int nId = pT->GetDlgCtrlID();
+               NMHDR nmhdr = { pT->m_hWnd, nId, ZSN_ZOOMCHANGED };
+               ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr);
+       }
+
+       BEGIN_MSG_MAP(CZoomScrollImpl)
+               MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
+               MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
+               MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
+               MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
+               MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+               MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
+               MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
+               MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
+               COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
+               COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
+       END_MSG_MAP()
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               ATLASSERT(m_sizeLogAll.cx >= 0 && m_sizeLogAll.cy >= 0);
+               ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
+
+               if(wParam != NULL)
+               {
+                       CDCHandle dc = (HDC)wParam;
+                       int nMapModeSav = dc.GetMapMode();
+                       dc.SetMapMode(MM_ANISOTROPIC);
+                       SIZE szWindowExt = { 0, 0 };
+                       dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
+                       SIZE szViewportExt = { 0, 0 };
+                       dc.SetViewportExt(m_sizeAll, &szViewportExt);
+                       POINT ptViewportOrg = { 0, 0 };
+                       dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
+
+                       pT->DoPaint(dc);
+
+                       dc.SetMapMode(nMapModeSav);
+                       dc.SetWindowExt(szWindowExt);
+                       dc.SetViewportExt(szViewportExt);
+                       dc.SetViewportOrg(ptViewportOrg);
+               }
+               else
+               {
+                       CPaintDC dc(pT->m_hWnd);
+                       pT->PrepareDC(dc.m_hDC);
+                       pT->DoPaint(dc.m_hDC);
+               }
+               return 0;
+       }
+
+       LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking)
+               {
+                       T* pT = static_cast<T*>(this);
+                       POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+                       if(pT->PtInDevRect(pt))
+                       {
+                               pT->SetCapture();
+                               m_bTracking = true;
+                               ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y);
+                       }       
+               }
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if(m_bTracking)
+               {
+                       T* pT = static_cast<T*>(this);
+                       POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+                       if(pT->PtInDevRect(pt))
+                       {
+                               pT->DrawTrackRect();
+                               m_rcTrack.right = pt.x;
+                               m_rcTrack.bottom = pt.y;
+                               pT->DrawTrackRect();
+                       }
+               }
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               ::ReleaseCapture();
+               if(m_nZoomMode == ZOOMMODE_OUT)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta);
+                       pT->NotifyParentZoomChanged();
+               }
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_bTracking)
+               {
+                       m_bTracking = false;
+                       T* pT = static_cast<T*>(this);
+                       pT->DrawTrackRect();
+                       pT->Zoom(m_rcTrack);
+                       pT->NotifyParentZoomChanged();
+                       ::SetRectEmpty(&m_rcTrack);
+               }
+               bHandled = FALSE;
+               return 0;
+       }       
+
+       LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF)
+               {
+                       T* pT = static_cast<T*>(this);
+                       if((HWND)wParam == pT->m_hWnd)
+                       {
+                               DWORD dwPos = ::GetMessagePos();
+                               POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
+                               pT->ScreenToClient(&pt);
+                               if(pT->PtInDevRect(pt))
+                               {
+                                       ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
+                                       return 1;
+                               }
+                       }
+               }
+               bHandled = FALSE;
+               return 0;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CZoomScrollWindowImpl - Implements scrolling window with zooming
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
+{
+public:
+       BEGIN_MSG_MAP(CZoomScrollWindowImpl)
+               MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
+               MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
+               MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
+               MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
+               MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
+               MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
+               MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint)
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
+               MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
+               MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
+               MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
+       ALT_MSG_MAP(1)
+               COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
+               COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
+               COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
+               COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
+               COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
+       END_MSG_MAP()
+};
+
+#endif // !_WIN32_WCE
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CScrollContainer
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits >
+{
+public:
+       DECLARE_WND_CLASS_EX(NULL, 0, -1)
+
+       typedef CScrollWindowImpl< T, TBase, TWinTraits >   _baseClass;
+
+// Data members
+       ATL::CWindow m_wndClient;
+       bool m_bAutoSizeClient;
+       bool m_bDrawEdgeIfEmpty;
+
+// Constructor
+       CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false)
+       {
+               // Set CScrollWindowImpl extended style
+               SetScrollExtendedStyle(SCRL_SCROLLCHILDREN);
+       }
+
+// Attributes
+       HWND GetClient() const
+       {
+               return m_wndClient;
+       }
+
+       HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               HWND hWndOldClient = m_wndClient;
+               m_wndClient = hWndClient;
+
+               SetRedraw(FALSE);
+               SetScrollSize(1, 1, FALSE);
+
+               if(m_wndClient.m_hWnd != NULL)
+               {
+                       m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+
+                       if(bClientSizeAsMin)
+                       {
+                               RECT rect = { 0 };
+                               m_wndClient.GetWindowRect(&rect);
+                               if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0)
+                                       SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE);
+                       }
+
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateLayout();
+               }
+
+               SetRedraw(TRUE);
+               RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
+
+               return hWndOldClient;
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CScrollContainerImpl)
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               CHAIN_MSG_MAP(_baseClass)
+               FORWARD_NOTIFICATIONS()
+       ALT_MSG_MAP(1)
+               CHAIN_MSG_MAP_ALT(_baseClass, 1)
+       END_MSG_MAP()
+
+       LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(m_wndClient.m_hWnd != NULL)
+                       m_wndClient.SetFocus();
+
+               return 0;
+       }
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;   // no background needed
+       }
+
+       LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               BOOL bTmp = TRUE;
+               LRESULT lRet = _baseClass::OnSize(uMsg, wParam, lParam, bTmp);
+
+               T* pT = static_cast<T*>(this);
+               pT->UpdateLayout();
+
+               return lRet;
+       }
+
+// Overrides for CScrollWindowImpl
+       void DoPaint(CDCHandle dc)
+       {
+               if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       RECT rect = { 0 };
+                       pT->GetContainerRect(rect);
+
+                       if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL)
+                               dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+
+                       dc.FillRect(&rect, COLOR_APPWORKSPACE);
+               }
+       }
+
+       void ScrollToView(POINT pt)
+       {
+               CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt);
+       }
+
+       void ScrollToView(RECT& rect)
+       {
+               CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect);
+       }
+
+       void ScrollToView(HWND hWnd)   // client window coordinates
+       {
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               ATLASSERT(m_wndClient.IsWindow());
+
+               RECT rect = { 0 };
+               ::GetWindowRect(hWnd, &rect);
+               ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2);
+               ScrollToView(rect);
+       }
+
+// Implementation - overrideable methods
+       void UpdateLayout()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       RECT rect = { 0 };
+                       pT->GetContainerRect(rect);
+
+                       m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
+               }
+               else
+               {
+                       Invalidate();
+               }
+       }
+
+       void GetContainerRect(RECT& rect)
+       {
+               GetClientRect(&rect);
+
+               if(rect.right < m_sizeAll.cx)
+                       rect.right = m_sizeAll.cx;
+
+               if(rect.bottom < m_sizeAll.cy)
+                       rect.bottom = m_sizeAll.cy;
+       }
+};
+
+class CScrollContainer : public CScrollContainerImpl<CScrollContainer>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1)
+};
+
+}; // namespace WTL
+
+#endif // __ATLSCRL_H__
diff --git a/include/WTL/Include/atlsplit.h b/include/WTL/Include/atlsplit.h
new file mode 100644 (file)
index 0000000..88cc1ea
--- /dev/null
@@ -0,0 +1,892 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLSPLIT_H__
+#define __ATLSPLIT_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlsplit.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atlsplit.h requires atlwin.h to be included first
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CSplitterImpl<T, t_bVertical>
+// CSplitterWindowImpl<T, t_bVertical, TBase, TWinTraits>
+// CSplitterWindowT<t_bVertical>
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CSplitterImpl - Provides splitter support to any window
+
+// Splitter panes constants
+#define SPLIT_PANE_LEFT                         0
+#define SPLIT_PANE_RIGHT                1
+#define SPLIT_PANE_TOP                  SPLIT_PANE_LEFT
+#define SPLIT_PANE_BOTTOM               SPLIT_PANE_RIGHT
+#define SPLIT_PANE_NONE                        -1
+
+// Splitter extended styles
+#define SPLIT_PROPORTIONAL             0x00000001
+#define SPLIT_NONINTERACTIVE           0x00000002
+#define SPLIT_RIGHTALIGNED             0x00000004
+#define SPLIT_BOTTOMALIGNED            SPLIT_RIGHTALIGNED
+
+// Note: SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED are 
+// mutually exclusive. If both are set, splitter defaults to SPLIT_PROPORTIONAL
+
+
+template <class T, bool t_bVertical = true>
+class CSplitterImpl
+{
+public:
+       enum { m_nPanesCount = 2, m_nPropMax = 10000 };
+
+       HWND m_hWndPane[m_nPanesCount];
+       RECT m_rcSplitter;
+       int m_xySplitterPos;
+       int m_nDefActivePane;
+       int m_cxySplitBar;              // splitter bar width/height
+       static HCURSOR m_hCursor;
+       int m_cxyMin;                   // minimum pane size
+       int m_cxyBarEdge;               // splitter bar edge
+       bool m_bFullDrag;
+       int m_cxyDragOffset;
+       int m_nProportionalPos;
+       bool m_bUpdateProportionalPos;
+       DWORD m_dwExtendedStyle;       // splitter specific extended styles
+       int m_nSinglePane;             // single pane mode
+
+// Constructor
+       CSplitterImpl() :
+                       m_xySplitterPos(-1), m_nDefActivePane(SPLIT_PANE_NONE), 
+                       m_cxySplitBar(0), m_cxyMin(0), m_cxyBarEdge(0), m_bFullDrag(true), 
+                       m_cxyDragOffset(0), m_nProportionalPos(0), m_bUpdateProportionalPos(true),
+                       m_dwExtendedStyle(SPLIT_PROPORTIONAL),
+                       m_nSinglePane(SPLIT_PANE_NONE)
+       {
+               m_hWndPane[SPLIT_PANE_LEFT] = NULL;
+               m_hWndPane[SPLIT_PANE_RIGHT] = NULL;
+
+               ::SetRectEmpty(&m_rcSplitter);
+
+               if(m_hCursor == NULL)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CSplitterImpl::CSplitterImpl.\n"));
+                               ATLASSERT(FALSE);
+                               return;
+                       }
+
+                       if(m_hCursor == NULL)
+                               m_hCursor = ::LoadCursor(NULL, t_bVertical ? IDC_SIZEWE : IDC_SIZENS);
+
+                       lock.Unlock();
+               }
+       }
+
+// Attributes
+       void SetSplitterRect(LPRECT lpRect = NULL, bool bUpdate = true)
+       {
+               if(lpRect == NULL)
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->GetClientRect(&m_rcSplitter);
+               }
+               else
+               {
+                       m_rcSplitter = *lpRect;
+               }
+
+               if(IsProportional())
+                       UpdateProportionalPos();
+               else if(IsRightAligned())
+                       UpdateRightAlignPos();
+
+               if(bUpdate)
+                       UpdateSplitterLayout();
+       }
+
+       void GetSplitterRect(LPRECT lpRect) const
+       {
+               ATLASSERT(lpRect != NULL);
+               *lpRect = m_rcSplitter;
+       }
+
+       bool SetSplitterPos(int xyPos = -1, bool bUpdate = true)
+       {
+               if(xyPos == -1)   // -1 == middle
+               {
+                       if(t_bVertical)
+                               xyPos = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2;
+                       else
+                               xyPos = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2;
+               }
+
+               // Adjust if out of valid range
+               int cxyMax = 0;
+               if(t_bVertical)
+                       cxyMax = m_rcSplitter.right - m_rcSplitter.left;
+               else
+                       cxyMax = m_rcSplitter.bottom - m_rcSplitter.top;
+
+               if(xyPos < m_cxyMin + m_cxyBarEdge)
+                       xyPos = m_cxyMin;
+               else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin))
+                       xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin;
+
+               // Set new position and update if requested
+               bool bRet = (m_xySplitterPos != xyPos);
+               m_xySplitterPos = xyPos;
+
+               if(m_bUpdateProportionalPos)
+               {
+                       if(IsProportional())
+                               StoreProportionalPos();
+                       else if(IsRightAligned())
+                               StoreRightAlignPos();
+               }
+               else
+               {
+                       m_bUpdateProportionalPos = true;
+               }
+
+               if(bUpdate && bRet)
+                       UpdateSplitterLayout();
+
+               return bRet;
+       }
+
+       void SetSplitterPosPct(int nPct, bool bUpdate = true)
+       {
+               ATLASSERT(nPct >= 0 && nPct <= 100);
+
+               m_nProportionalPos = ::MulDiv(nPct, m_nPropMax, 100);
+               UpdateProportionalPos();
+
+               if(bUpdate)
+                       UpdateSplitterLayout();
+       }
+
+       int GetSplitterPos() const
+       {
+               return m_xySplitterPos;
+       }
+
+       bool SetSinglePaneMode(int nPane = SPLIT_PANE_NONE)
+       {
+               ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE);
+               if(!(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE))
+                       return false;
+
+               if(nPane != SPLIT_PANE_NONE)
+               {
+                       if(!::IsWindowVisible(m_hWndPane[nPane]))
+                               ::ShowWindow(m_hWndPane[nPane], SW_SHOW);
+                       int nOtherPane = (nPane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT;
+                       ::ShowWindow(m_hWndPane[nOtherPane], SW_HIDE);
+                       if(m_nDefActivePane != nPane)
+                               m_nDefActivePane = nPane;
+               }
+               else if(m_nSinglePane != SPLIT_PANE_NONE)
+               {
+                       int nOtherPane = (m_nSinglePane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT;
+                       ::ShowWindow(m_hWndPane[nOtherPane], SW_SHOW);
+               }
+
+               m_nSinglePane = nPane;
+               UpdateSplitterLayout();
+               return true;
+       }
+
+       int GetSinglePaneMode() const
+       {
+               return m_nSinglePane;
+       }
+
+       DWORD GetSplitterExtendedStyle() const
+       {
+               return m_dwExtendedStyle;
+       }
+
+       DWORD SetSplitterExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
+       {
+               DWORD dwPrevStyle = m_dwExtendedStyle;
+               if(dwMask == 0)
+                       m_dwExtendedStyle = dwExtendedStyle;
+               else
+                       m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
+#ifdef _DEBUG
+               if(IsProportional() && IsRightAligned())
+                       ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::SetSplitterExtendedStyle - SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED are mutually exclusive, defaulting to SPLIT_PROPORTIONAL.\n"));
+#endif // _DEBUG
+               return dwPrevStyle;
+       }
+
+// Splitter operations
+       void SetSplitterPanes(HWND hWndLeftTop, HWND hWndRightBottom, bool bUpdate = true)
+       {
+               m_hWndPane[SPLIT_PANE_LEFT] = hWndLeftTop;
+               m_hWndPane[SPLIT_PANE_RIGHT] = hWndRightBottom;
+               ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]);
+               if(bUpdate)
+                       UpdateSplitterLayout();
+       }
+
+       bool SetSplitterPane(int nPane, HWND hWnd, bool bUpdate = true)
+       {
+               ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
+
+               if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT)
+                       return false;
+               m_hWndPane[nPane] = hWnd;
+               ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]);
+               if(bUpdate)
+                       UpdateSplitterLayout();
+               return true;
+       }
+
+       HWND GetSplitterPane(int nPane) const
+       {
+               ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
+
+               if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT)
+                       return false;
+               return m_hWndPane[nPane];
+       }
+
+       bool SetActivePane(int nPane)
+       {
+               ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
+
+               if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT)
+                       return false;
+               if(m_nSinglePane != SPLIT_PANE_NONE && nPane != m_nSinglePane)
+                       return false;
+               ::SetFocus(m_hWndPane[nPane]);
+               m_nDefActivePane = nPane;
+               return true;
+       }
+
+       int GetActivePane() const
+       {
+               int nRet = SPLIT_PANE_NONE;
+               HWND hWndFocus = ::GetFocus();
+               if(hWndFocus != NULL)
+               {
+                       for(int nPane = 0; nPane < m_nPanesCount; nPane++)
+                       {
+                               if(hWndFocus == m_hWndPane[nPane] || ::IsChild(m_hWndPane[nPane], hWndFocus))
+                               {
+                                       nRet = nPane;
+                                       break;
+                               }
+                       }
+               }
+               return nRet;
+       }
+
+       bool ActivateNextPane(bool bNext = true)
+       {
+               int nPane = m_nSinglePane;
+               if(nPane == SPLIT_PANE_NONE)
+               {
+                       switch(GetActivePane())
+                       {
+                       case SPLIT_PANE_LEFT:
+                               nPane = SPLIT_PANE_RIGHT;
+                               break;
+                       case SPLIT_PANE_RIGHT:
+                               nPane = SPLIT_PANE_LEFT;
+                               break;
+                       default:
+                               nPane = bNext ? SPLIT_PANE_LEFT : SPLIT_PANE_RIGHT;
+                               break;
+                       }
+               }
+               return SetActivePane(nPane);
+       }
+
+       bool SetDefaultActivePane(int nPane)
+       {
+               ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
+
+               if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT)
+                       return false;
+               m_nDefActivePane = nPane;
+               return true;
+       }
+
+       bool SetDefaultActivePane(HWND hWnd)
+       {
+               for(int nPane = 0; nPane < m_nPanesCount; nPane++)
+               {
+                       if(hWnd == m_hWndPane[nPane])
+                       {
+                               m_nDefActivePane = nPane;
+                               return true;
+                       }
+               }
+               return false;   // not found
+       }
+
+       int GetDefaultActivePane() const
+       {
+               return m_nDefActivePane;
+       }
+
+       void DrawSplitter(CDCHandle dc)
+       {
+               ATLASSERT(dc.m_hDC != NULL);
+               if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1)
+                       return;
+
+               T* pT = static_cast<T*>(this);
+               if(m_nSinglePane == SPLIT_PANE_NONE)
+               {
+                       pT->DrawSplitterBar(dc);
+
+                       for(int nPane = 0; nPane < m_nPanesCount; nPane++)
+                       {
+                               if(m_hWndPane[nPane] == NULL)
+                                       pT->DrawSplitterPane(dc, nPane);
+                       }
+               }
+               else
+               {
+                       if(m_hWndPane[m_nSinglePane] == NULL)
+                               pT->DrawSplitterPane(dc, m_nSinglePane);
+               }
+       }
+
+// Overrideables
+       void DrawSplitterBar(CDCHandle dc)
+       {
+               RECT rect;
+               if(GetSplitterBarRect(&rect))
+               {
+                       dc.FillRect(&rect, COLOR_3DFACE);
+                       // draw 3D edge if needed
+                       T* pT = static_cast<T*>(this);
+                       if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0)
+                               dc.DrawEdge(&rect, EDGE_RAISED, t_bVertical ? (BF_LEFT | BF_RIGHT) : (BF_TOP | BF_BOTTOM));
+               }
+       }
+
+       // called only if pane is empty
+       void DrawSplitterPane(CDCHandle dc, int nPane)
+       {
+               RECT rect;
+               if(GetSplitterPaneRect(nPane, &rect))
+               {
+                       T* pT = static_cast<T*>(this);
+                       if((pT->GetExStyle() & WS_EX_CLIENTEDGE) == 0)
+                               dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+                       dc.FillRect(&rect, COLOR_APPWORKSPACE);
+               }
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CSplitterImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+#endif // !_WIN32_WCE
+               if(IsInteractive())
+               {
+                       MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
+                       MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
+                       MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+                       MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
+                       MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDoubleClick)
+                       MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
+               }
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+#ifndef _WIN32_WCE
+               MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
+#endif // !_WIN32_WCE
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               GetSystemSettings(false);
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               // try setting position if not set
+               if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1)
+                       pT->SetSplitterPos();
+               // do painting
+               CPaintDC dc(pT->m_hWnd);
+               pT->DrawSplitter(dc.m_hDC);
+               return 0;
+       }
+
+       LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               if((HWND)wParam == pT->m_hWnd && LOWORD(lParam) == HTCLIENT)
+               {
+                       DWORD dwPos = ::GetMessagePos();
+                       POINT ptPos = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
+                       pT->ScreenToClient(&ptPos);
+                       if(IsOverSplitterBar(ptPos.x, ptPos.y))
+                               return 1;
+               }
+
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               int xPos = GET_X_LPARAM(lParam);
+               int yPos = GET_Y_LPARAM(lParam);
+               if((wParam & MK_LBUTTON) && ::GetCapture() == pT->m_hWnd)
+               {
+                       int xyNewSplitPos = 0;
+                       if(t_bVertical)
+                               xyNewSplitPos = xPos - m_rcSplitter.left - m_cxyDragOffset;
+                       else
+                               xyNewSplitPos = yPos - m_rcSplitter.top - m_cxyDragOffset;
+
+                       if(xyNewSplitPos == -1)   // avoid -1, that means middle
+                               xyNewSplitPos = -2;
+
+                       if(m_xySplitterPos != xyNewSplitPos)
+                       {
+                               if(m_bFullDrag)
+                               {
+                                       if(pT->SetSplitterPos(xyNewSplitPos, true))
+                                               pT->UpdateWindow();
+                               }
+                               else
+                               {
+                                       DrawGhostBar();
+                                       pT->SetSplitterPos(xyNewSplitPos, false);
+                                       DrawGhostBar();
+                               }
+                       }
+               }
+               else            // not dragging, just set cursor
+               {
+                       if(IsOverSplitterBar(xPos, yPos))
+                               ::SetCursor(m_hCursor);
+                       bHandled = FALSE;
+               }
+
+               return 0;
+       }
+
+       LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               int xPos = GET_X_LPARAM(lParam);
+               int yPos = GET_Y_LPARAM(lParam);
+               if(IsOverSplitterBar(xPos, yPos))
+               {
+                       T* pT = static_cast<T*>(this);
+                       pT->SetCapture();
+                       ::SetCursor(m_hCursor);
+                       if(!m_bFullDrag)
+                               DrawGhostBar();
+                       if(t_bVertical)
+                               m_cxyDragOffset = xPos - m_rcSplitter.left - m_xySplitterPos;
+                       else
+                               m_cxyDragOffset = yPos - m_rcSplitter.top - m_xySplitterPos;
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               ::ReleaseCapture();
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnLButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetSplitterPos();   // middle
+               return 0;
+       }
+
+       LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(!m_bFullDrag)
+               {
+                       DrawGhostBar();
+                       UpdateSplitterLayout();
+                       T* pT = static_cast<T*>(this);
+                       pT->UpdateWindow();
+               }
+               return 0;
+       }
+
+       LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM, BOOL& bHandled)
+       {
+               if(m_nSinglePane == SPLIT_PANE_NONE)
+               {
+                       if(m_nDefActivePane == SPLIT_PANE_LEFT || m_nDefActivePane == SPLIT_PANE_RIGHT)
+                               ::SetFocus(m_hWndPane[m_nDefActivePane]);
+               }
+               else
+               {
+                       ::SetFocus(m_hWndPane[m_nSinglePane]);
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
+               if(lRet == MA_ACTIVATE || lRet == MA_ACTIVATEANDEAT)
+               {
+                       DWORD dwPos = ::GetMessagePos();
+                       POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
+                       pT->ScreenToClient(&pt);
+                       RECT rcPane;
+                       for(int nPane = 0; nPane < m_nPanesCount; nPane++)
+                       {
+                               if(GetSplitterPaneRect(nPane, &rcPane) && ::PtInRect(&rcPane, pt))
+                               {
+                                       m_nDefActivePane = nPane;
+                                       break;
+                               }
+                       }
+               }
+               return lRet;
+       }
+#endif // !_WIN32_WCE
+
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               GetSystemSettings(true);
+               return 0;
+       }
+
+// Implementation - internal helpers
+       void UpdateSplitterLayout()
+       {
+               if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1)
+                       return;
+
+               T* pT = static_cast<T*>(this);
+               RECT rect = { 0, 0, 0, 0 };
+               if(m_nSinglePane == SPLIT_PANE_NONE)
+               {
+                       if(GetSplitterBarRect(&rect))
+                               pT->InvalidateRect(&rect);
+
+                       for(int nPane = 0; nPane < m_nPanesCount; nPane++)
+                       {
+                               if(GetSplitterPaneRect(nPane, &rect))
+                               {
+                                       if(m_hWndPane[nPane] != NULL)
+                                               ::SetWindowPos(m_hWndPane[nPane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
+                                       else
+                                               pT->InvalidateRect(&rect);
+                               }
+                       }
+               }
+               else
+               {
+                       if(GetSplitterPaneRect(m_nSinglePane, &rect))
+                       {
+                               if(m_hWndPane[m_nSinglePane] != NULL)
+                                       ::SetWindowPos(m_hWndPane[m_nSinglePane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
+                               else
+                                       pT->InvalidateRect(&rect);
+                       }
+               }
+       }
+
+       bool GetSplitterBarRect(LPRECT lpRect) const
+       {
+               ATLASSERT(lpRect != NULL);
+               if(m_nSinglePane != SPLIT_PANE_NONE || m_xySplitterPos == -1)
+                       return false;
+
+               if(t_bVertical)
+               {
+                       lpRect->left = m_rcSplitter.left + m_xySplitterPos;
+                       lpRect->top = m_rcSplitter.top;
+                       lpRect->right = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
+                       lpRect->bottom = m_rcSplitter.bottom;
+               }
+               else
+               {
+                       lpRect->left = m_rcSplitter.left;
+                       lpRect->top = m_rcSplitter.top + m_xySplitterPos;
+                       lpRect->right = m_rcSplitter.right;
+                       lpRect->bottom = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
+               }
+
+               return true;
+       }
+
+       bool GetSplitterPaneRect(int nPane, LPRECT lpRect) const
+       {
+               ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
+               ATLASSERT(lpRect != NULL);
+               bool bRet = true;
+               if(m_nSinglePane != SPLIT_PANE_NONE)
+               {
+                       if(nPane == m_nSinglePane)
+                               *lpRect = m_rcSplitter;
+                       else
+                               bRet = false;
+               }
+               else if(nPane == SPLIT_PANE_LEFT)
+               {
+                       if(t_bVertical)
+                       {
+                               lpRect->left = m_rcSplitter.left;
+                               lpRect->top = m_rcSplitter.top;
+                               lpRect->right = m_rcSplitter.left + m_xySplitterPos;
+                               lpRect->bottom = m_rcSplitter.bottom;
+                       }
+                       else
+                       {
+                               lpRect->left = m_rcSplitter.left;
+                               lpRect->top = m_rcSplitter.top;
+                               lpRect->right = m_rcSplitter.right;
+                               lpRect->bottom = m_rcSplitter.top + m_xySplitterPos;
+                       }
+               }
+               else if(nPane == SPLIT_PANE_RIGHT)
+               {
+                       if(t_bVertical)
+                       {
+                               lpRect->left = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
+                               lpRect->top = m_rcSplitter.top;
+                               lpRect->right = m_rcSplitter.right;
+                               lpRect->bottom = m_rcSplitter.bottom;
+                       }
+                       else
+                       {
+                               lpRect->left = m_rcSplitter.left;
+                               lpRect->top = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
+                               lpRect->right = m_rcSplitter.right;
+                               lpRect->bottom = m_rcSplitter.bottom;
+                       }
+               }
+               else
+               {
+                       bRet = false;
+               }
+               return bRet;
+       }
+
+       bool IsOverSplitterRect(int x, int y) const
+       {
+               // -1 == don't check
+               return ((x == -1 || (x >= m_rcSplitter.left && x <= m_rcSplitter.right)) &&
+                       (y == -1 || (y >= m_rcSplitter.top && y <= m_rcSplitter.bottom)));
+       }
+
+       bool IsOverSplitterBar(int x, int y) const
+       {
+               if(m_nSinglePane != SPLIT_PANE_NONE)
+                       return false;
+               if(m_xySplitterPos == -1 || !IsOverSplitterRect(x, y))
+                       return false;
+               int xy = t_bVertical ? x : y;
+               int xyOff = t_bVertical ? m_rcSplitter.left : m_rcSplitter.top;
+               return ((xy >= (xyOff + m_xySplitterPos)) && (xy < xyOff + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge));
+       }
+
+       void DrawGhostBar()
+       {
+               RECT rect = { 0, 0, 0, 0 };
+               if(GetSplitterBarRect(&rect))
+               {
+                       // invert the brush pattern (looks just like frame window sizing)
+                       T* pT = static_cast<T*>(this);
+                       CWindowDC dc(pT->m_hWnd);
+                       CBrush brush = CDCHandle::GetHalftoneBrush();
+                       if(brush.m_hBrush != NULL)
+                       {
+                               CBrushHandle brushOld = dc.SelectBrush(brush);
+                               dc.PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
+                               dc.SelectBrush(brushOld);
+                       }
+               }
+       }
+
+       void GetSystemSettings(bool bUpdate)
+       {
+#ifndef _WIN32_WCE
+               m_cxySplitBar = ::GetSystemMetrics(t_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME);
+#else // CE specific
+               m_cxySplitBar = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE);
+#endif // _WIN32_WCE
+
+               T* pT = static_cast<T*>(this);
+               if((pT->GetExStyle() & WS_EX_CLIENTEDGE))
+               {
+                       m_cxyBarEdge = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE);
+                       m_cxyMin = 0;
+               }
+               else
+               {
+                       m_cxyBarEdge = 0;
+                       m_cxyMin = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE);
+               }
+
+#ifndef _WIN32_WCE
+               ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0);
+#endif // !_WIN32_WCE
+
+               if(bUpdate)
+                       UpdateSplitterLayout();
+       }
+
+       bool IsProportional() const
+       {
+               return ((m_dwExtendedStyle & SPLIT_PROPORTIONAL) != 0);
+       }
+
+       void StoreProportionalPos()
+       {
+               int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
+               if(cxyTotal > 0)
+                       m_nProportionalPos = ::MulDiv(m_xySplitterPos, m_nPropMax, cxyTotal);
+               else
+                       m_nProportionalPos = 0;
+               ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreProportionalPos - %i\n"), m_nProportionalPos);
+       }
+
+       void UpdateProportionalPos()
+       {
+               int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
+               if(cxyTotal > 0)
+               {
+                       int xyNewPos = ::MulDiv(m_nProportionalPos, cxyTotal, m_nPropMax);
+                       m_bUpdateProportionalPos = false;
+                       T* pT = static_cast<T*>(this);
+                       pT->SetSplitterPos(xyNewPos, false);
+               }
+       }
+
+       bool IsRightAligned() const
+       {
+               return ((m_dwExtendedStyle & SPLIT_RIGHTALIGNED) != 0);
+       }
+
+       void StoreRightAlignPos()
+       {
+               int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
+               if(cxyTotal > 0)
+                       m_nProportionalPos = cxyTotal - m_xySplitterPos;
+               else
+                       m_nProportionalPos = 0;
+               ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreRightAlignPos - %i\n"), m_nProportionalPos);
+       }
+
+       void UpdateRightAlignPos()
+       {
+               int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
+               if(cxyTotal > 0)
+               {
+                       m_bUpdateProportionalPos = false;
+                       T* pT = static_cast<T*>(this);
+                       pT->SetSplitterPos(cxyTotal - m_nProportionalPos, false);
+               }
+       }
+
+       bool IsInteractive() const
+       {
+               return ((m_dwExtendedStyle & SPLIT_NONINTERACTIVE) == 0);
+       }
+};
+
+template <class T, bool t_bVertical> HCURSOR CSplitterImpl< T, t_bVertical>::m_hCursor = NULL;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CSplitterWindowImpl - Implements a splitter window
+
+template <class T, bool t_bVertical = true, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CSplitterWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CSplitterImpl< T , t_bVertical >
+{
+public:
+       DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, COLOR_WINDOW)
+
+       typedef CSplitterImpl< T , t_bVertical >   _baseClass;
+
+       BEGIN_MSG_MAP(CSplitterWindowImpl)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               CHAIN_MSG_MAP(_baseClass)
+               FORWARD_NOTIFICATIONS()
+       END_MSG_MAP()
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // handled, no background painting needed
+               return 1;
+       }
+
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(wParam != SIZE_MINIMIZED)
+                       SetSplitterRect();
+
+               bHandled = FALSE;
+               return 1;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CSplitterWindow - Implements a splitter window to be used as is
+
+template <bool t_bVertical = true>
+class CSplitterWindowT : public CSplitterWindowImpl<CSplitterWindowT<t_bVertical>, t_bVertical>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("WTL_SplitterWindow"), CS_DBLCLKS, COLOR_WINDOW)
+};
+
+typedef CSplitterWindowT<true>    CSplitterWindow;
+typedef CSplitterWindowT<false>   CHorSplitterWindow;
+
+}; // namespace WTL
+
+#endif // __ATLSPLIT_H__
diff --git a/include/WTL/Include/atltheme.h b/include/WTL/Include/atltheme.h
new file mode 100644 (file)
index 0000000..12c6059
--- /dev/null
@@ -0,0 +1,1222 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLTHEME_H__
+#define __ATLTHEME_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifdef _WIN32_WCE
+       #error atltheme.h is not supported on Windows CE
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atltheme.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atltheme.h requires atlwin.h to be included first
+#endif
+
+#if (_WIN32_WINNT < 0x0501)
+       #error atltheme.h requires _WIN32_WINNT >= 0x0501
+#endif // (_WIN32_WINNT < 0x0501)
+
+#if defined(_WTL_USE_VSSYM32) || (defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN))
+  #include <vssym32.h>
+#else
+  #ifndef TMSCHEMA_H
+  #include <tmschema.h>
+  #endif
+#endif
+
+#ifndef _UXTHEME_H_
+#include <uxtheme.h>
+#endif
+#pragma comment(lib, "uxtheme.lib")
+
+// Note: To create an application that also runs on older versions of Windows,
+// use delay load of uxtheme.dll and ensure that no calls to the Theme API are
+// made if theming is not supported. It is enough to check if m_hTheme is NULL.
+// Example:
+//     if(m_hTheme != NULL)
+//     {
+//             DrawThemeBackground(dc, BP_PUSHBUTTON, PBS_NORMAL, &rect, NULL);
+//             DrawThemeText(dc, BP_PUSHBUTTON, PBS_NORMAL, L"Button", -1, DT_SINGLELINE | DT_CENTER | DT_VCENTER, 0, &rect);
+//     }
+//     else
+//     {
+//             dc.DrawFrameControl(&rect, DFC_BUTTON, DFCS_BUTTONPUSH);
+//             dc.DrawText(_T("Button"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+//     }
+//
+// Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib, 
+// and add uxtheme.dll in the Linker.Input.Delay Loaded DLLs section of the 
+// project properties.
+#if (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD)
+  #pragma comment(lib, "delayimp.lib")
+  #pragma comment(linker, "/delayload:uxtheme.dll")
+#endif // (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD)
+
+// Hack: Signatures in uxtheme.h changed - the only way to check which variant of uxtheme.h
+// is included is to check for presence of new defines MAX_THEMECOLOR and MAX_THEMESIZE
+#ifndef _WTL_NEW_UXTHEME
+  #if defined(MAX_THEMECOLOR) && defined(MAX_THEMESIZE)
+    #define _WTL_NEW_UXTHEME
+  #endif // defined(MAX_THEMECOLOR) && defined(MAX_THEMESIZE)
+#endif // _WTL_NEW_UXTHEME
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CTheme
+// CThemeImpl<T, TBase>
+//
+// CBufferedPaint
+// CBufferedPaintImpl<T>
+// CBufferedPaintWindowImpl<T, TBase, TWinTraits>
+// CBufferedAnimation
+// CBufferedAnimationImpl<T, TState>
+// CBufferedAnimationWindowImpl<T, TState, TBase, TWinTraits>
+//
+// Global functions:
+//   AtlDrawThemeClientEdge()
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CTheme - wrapper for theme handle
+
+class CTheme
+{
+public:
+// Data members
+       HTHEME m_hTheme;
+       static int m_nIsThemingSupported;
+
+// Constructor
+       CTheme(HTHEME hTheme = NULL) : m_hTheme(hTheme)
+       {
+               IsThemingSupported();
+       }
+
+// Operators and helpers
+       bool IsThemeNull() const
+       {
+               return (m_hTheme == NULL);
+       }
+
+       CTheme& operator =(HTHEME hTheme)
+       {
+               m_hTheme = hTheme;
+               return *this;
+       }
+
+       operator HTHEME() const
+       {
+               return m_hTheme;
+       }
+
+       void Attach(HTHEME hTheme)
+       {
+               m_hTheme = hTheme;
+       }
+
+       HTHEME Detach()
+       {
+               HTHEME hTheme = m_hTheme;
+               m_hTheme = NULL;
+               return hTheme;
+       }
+
+// Theme support helper
+       static bool IsThemingSupported()
+       {
+               if(m_nIsThemingSupported == -1)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CTheme::IsThemingSupported.\n"));
+                               ATLASSERT(FALSE);
+                               return false;
+                       }
+
+                       if(m_nIsThemingSupported == -1)
+                       {
+                               HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
+                               m_nIsThemingSupported = (hThemeDLL != NULL) ? 1 : 0;
+                               if(hThemeDLL != NULL)
+                                       ::FreeLibrary(hThemeDLL);
+                       }
+
+                       lock.Unlock();
+               }
+
+               ATLASSERT(m_nIsThemingSupported != -1);
+               return (m_nIsThemingSupported == 1);
+       }
+
+// Operations and theme properties
+       HTHEME OpenThemeData(HWND hWnd, LPCWSTR pszClassList)
+       {
+               if(!IsThemingSupported())
+                       return NULL;
+
+               ATLASSERT(m_hTheme == NULL);
+               m_hTheme = ::OpenThemeData(hWnd, pszClassList);
+               return m_hTheme;
+       }
+
+       HRESULT CloseThemeData()
+       {
+               HRESULT hRet = S_FALSE;
+               if(m_hTheme != NULL)
+               {
+                       hRet = ::CloseThemeData(m_hTheme);
+                       if(SUCCEEDED(hRet))
+                               m_hTheme = NULL;
+               }
+               return hRet;
+       }
+
+       HRESULT DrawThemeBackground(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, LPCRECT pClipRect = NULL)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::DrawThemeBackground(m_hTheme, hDC, nPartID, nStateID, pRect, pClipRect);
+       }
+
+       HRESULT DrawThemeBackgroundEx(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, const DTBGOPTS* pOptions = NULL)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::DrawThemeBackgroundEx(m_hTheme, hDC, nPartID, nStateID, pRect, pOptions);
+       }
+
+       HRESULT DrawThemeText(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::DrawThemeText(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, dwTextFlags2, pRect);
+       }
+
+       HRESULT GetThemeBackgroundContentRect(HDC hDC, int nPartID, int nStateID,  LPCRECT pBoundingRect, LPRECT pContentRect) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeBackgroundContentRect(m_hTheme, hDC, nPartID, nStateID,  pBoundingRect, pContentRect);
+       }
+
+       HRESULT GetThemeBackgroundExtent(HDC hDC, int nPartID, int nStateID, LPCRECT pContentRect, LPRECT pExtentRect) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeBackgroundExtent(m_hTheme, hDC, nPartID, nStateID, pContentRect, pExtentRect);
+       }
+
+       HRESULT GetThemePartSize(HDC hDC, int nPartID, int nStateID, LPRECT pRect, enum THEMESIZE eSize, LPSIZE pSize) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemePartSize(m_hTheme, hDC, nPartID, nStateID, pRect, eSize, pSize);
+       }
+
+       HRESULT GetThemeTextExtent(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, LPCRECT  pBoundingRect, LPRECT pExtentRect) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeTextExtent(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, pBoundingRect, pExtentRect);
+       }
+
+       HRESULT GetThemeTextMetrics(HDC hDC, int nPartID, int nStateID, PTEXTMETRICW pTextMetric) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+#ifdef _WTL_NEW_UXTHEME
+               return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, pTextMetric);
+#else // !_WTL_NEW_UXTHEME
+               // Note: The cast to PTEXTMETRIC is because uxtheme.h incorrectly uses it instead of PTEXTMETRICW
+               return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, (PTEXTMETRIC)pTextMetric);
+#endif // !_WTL_NEW_UXTHEME
+       }
+
+       HRESULT GetThemeBackgroundRegion(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HRGN* pRegion) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeBackgroundRegion(m_hTheme, hDC, nPartID, nStateID, pRect, pRegion);
+       }
+
+       HRESULT HitTestThemeBackground(HDC hDC, int nPartID, int nStateID, DWORD dwOptions, LPCRECT pRect, HRGN hrgn, POINT ptTest, WORD* pwHitTestCode) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::HitTestThemeBackground(m_hTheme, hDC, nPartID, nStateID, dwOptions, pRect, hrgn, ptTest, pwHitTestCode);
+       }
+
+       HRESULT DrawThemeEdge(HDC hDC, int nPartID, int nStateID, LPCRECT pDestRect, UINT uEdge, UINT uFlags, LPRECT pContentRect = NULL)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::DrawThemeEdge(m_hTheme, hDC, nPartID, nStateID, pDestRect, uEdge, uFlags, pContentRect);
+       }
+
+       HRESULT DrawThemeIcon(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HIMAGELIST himl, int nImageIndex)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::DrawThemeIcon(m_hTheme, hDC, nPartID, nStateID, pRect, himl, nImageIndex);
+       }
+
+       BOOL IsThemePartDefined(int nPartID, int nStateID) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::IsThemePartDefined(m_hTheme, nPartID, nStateID);
+       }
+
+       BOOL IsThemeBackgroundPartiallyTransparent(int nPartID, int nStateID) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::IsThemeBackgroundPartiallyTransparent(m_hTheme, nPartID, nStateID);
+       }
+
+       HRESULT GetThemeColor(int nPartID, int nStateID, int nPropID, COLORREF* pColor) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeColor(m_hTheme, nPartID, nStateID, nPropID, pColor);
+       }
+
+       HRESULT GetThemeMetric(HDC hDC, int nPartID, int nStateID, int nPropID, int* pnVal) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeMetric(m_hTheme, hDC, nPartID, nStateID, nPropID, pnVal);
+       }
+
+       HRESULT GetThemeString(int nPartID, int nStateID, int nPropID, LPWSTR pszBuff, int cchMaxBuffChars) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeString(m_hTheme, nPartID, nStateID, nPropID, pszBuff, cchMaxBuffChars);
+       }
+
+       HRESULT GetThemeBool(int nPartID, int nStateID, int nPropID, BOOL* pfVal) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeBool(m_hTheme, nPartID, nStateID, nPropID, pfVal);
+       }
+
+       HRESULT GetThemeInt(int nPartID, int nStateID, int nPropID, int* pnVal) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeInt(m_hTheme, nPartID, nStateID, nPropID, pnVal);
+       }
+
+       HRESULT GetThemeEnumValue(int nPartID, int nStateID, int nPropID, int* pnVal) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeEnumValue(m_hTheme, nPartID, nStateID, nPropID, pnVal);
+       }
+
+       HRESULT GetThemePosition(int nPartID, int nStateID, int nPropID, LPPOINT pPoint) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemePosition(m_hTheme, nPartID, nStateID, nPropID, pPoint);
+       }
+
+       // deprecated
+       HRESULT GetThemeFont(int nPartID, HDC hDC, int nStateID, int nPropID, LOGFONTW* pFont) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+#ifdef _WTL_NEW_UXTHEME
+               return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont);
+#else // !_WTL_NEW_UXTHEME
+               // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW*
+               return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, (LOGFONT*)pFont);
+#endif // !_WTL_NEW_UXTHEME
+       }
+
+       HRESULT GetThemeFont(HDC hDC, int nPartID, int nStateID, int nPropID, LOGFONTW* pFont) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+#ifdef _WTL_NEW_UXTHEME
+               return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont);
+#else // !_WTL_NEW_UXTHEME
+               // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW*
+               return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, (LOGFONT*)pFont);
+#endif // !_WTL_NEW_UXTHEME
+       }
+
+       HRESULT GetThemeRect(int nPartID, int nStateID, int nPropID, LPRECT pRect) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeRect(m_hTheme, nPartID, nStateID, nPropID, pRect);
+       }
+
+       HRESULT GetThemeMargins(HDC hDC, int nPartID, int nStateID, int nPropID, LPRECT pRect, PMARGINS pMargins) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeMargins(m_hTheme, hDC, nPartID, nStateID, nPropID, pRect, pMargins);
+       }
+
+       HRESULT GetThemeIntList(int nPartID, int nStateID, int nPropID, INTLIST* pIntList) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeIntList(m_hTheme, nPartID, nStateID, nPropID, pIntList);
+       }
+
+       HRESULT GetThemePropertyOrigin(int nPartID, int nStateID, int nPropID, enum PROPERTYORIGIN* pOrigin) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemePropertyOrigin(m_hTheme, nPartID, nStateID, nPropID, pOrigin);
+       }
+
+       HRESULT GetThemeFilename(int nPartID, int nStateID, int nPropID, LPWSTR pszThemeFileName, int cchMaxBuffChars) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeFilename(m_hTheme, nPartID, nStateID, nPropID, pszThemeFileName, cchMaxBuffChars);
+       }
+
+       COLORREF GetThemeSysColor(int nColorID) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeSysColor(m_hTheme, nColorID);
+       }
+
+       HBRUSH GetThemeSysColorBrush(int nColorID) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeSysColorBrush(m_hTheme, nColorID);
+       }
+
+       int GetThemeSysSize(int nSizeID) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeSysSize(m_hTheme, nSizeID);
+       }
+
+       BOOL GetThemeSysBool(int nBoolID) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeSysBool(m_hTheme, nBoolID);
+       }
+
+       HRESULT GetThemeSysFont(int nFontID, LOGFONTW* plf) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+#ifdef _WTL_NEW_UXTHEME
+               return ::GetThemeSysFont(m_hTheme, nFontID, plf);
+#else // !_WTL_NEW_UXTHEME
+               // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW*
+               return ::GetThemeSysFont(m_hTheme, nFontID, (LOGFONT*)plf);
+#endif // !_WTL_NEW_UXTHEME
+       }
+
+       HRESULT GetThemeSysString(int nStringID, LPWSTR pszStringBuff, int cchMaxStringChars) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeSysString(m_hTheme, nStringID, pszStringBuff, cchMaxStringChars);
+       }
+
+       HRESULT GetThemeSysInt(int nIntID, int* pnValue) const
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeSysInt(m_hTheme, nIntID, pnValue);
+       }
+
+#ifdef _WTL_NEW_UXTHEME
+       HTHEME OpenThemeDataEx(HWND hWnd, LPCWSTR pszClassList, DWORD dwFlags)
+       {
+               if(!IsThemingSupported())
+                       return NULL;
+
+               ATLASSERT(m_hTheme == NULL);
+               m_hTheme = ::OpenThemeDataEx(hWnd, pszClassList, dwFlags);
+               return m_hTheme;
+       }
+
+       HRESULT DrawThemeTextEx(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int cchText, DWORD dwTextFlags, LPRECT lpRect, const DTTOPTS* pOptions)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::DrawThemeTextEx(m_hTheme, hDC, nPartID, nStateID, pszText, cchText, dwTextFlags, lpRect, pOptions);
+       }
+
+       HRESULT GetThemeTransitionDuration(int nPartID, int nFromStateID, int nToStateID, int nPropID, DWORD& dwDuration)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeTransitionDuration(m_hTheme, nPartID, nFromStateID, nToStateID, nPropID, &dwDuration);
+       }
+#endif // _WTL_NEW_UXTHEME
+
+#if (_WIN32_WINNT >= 0x0600)
+       HRESULT GetThemeBitmap(int nPartID, int nStateID, int nPropID, ULONG uFlags, HBITMAP& hBitmap)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeBitmap(m_hTheme, nPartID, nStateID, nPropID, uFlags, &hBitmap);
+       }
+
+       HRESULT GetThemeStream(int nPartID, int nStateID, int nPropID, VOID** ppvStream, DWORD* pcbStream, HINSTANCE hInstance)
+       {
+               ATLASSERT(m_hTheme != NULL);
+               return ::GetThemeStream(m_hTheme, nPartID, nStateID, nPropID, ppvStream, pcbStream, hInstance);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+};
+
+__declspec(selectany) int CTheme::m_nIsThemingSupported = -1;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CThemeImpl - theme support implementation
+
+// Derive from this class to implement window with theme support.
+// Example:
+//     class CMyThemeWindow : public CWindowImpl<CMyThemeWindow>, public CThemeImpl<CMyThemeWindow>
+//     {
+//     ...
+//             BEGIN_MSG_MAP(CMyThemeWindow)
+//                     CHAIN_MSG_MAP(CThemeImpl<CMyThemeWindow>)
+//                     ...
+//             END_MSG_MAP()
+//     ...
+//     };
+//
+// If you set theme class list, the class will automaticaly open/close/reopen theme data.
+
+
+// Helper for drawing theme client edge
+inline bool AtlDrawThemeClientEdge(HTHEME hTheme, HWND hWnd, HRGN hRgnUpdate = NULL, HBRUSH hBrush = NULL, int nPartID = 0, int nStateID = 0)
+{
+       ATLASSERT(hTheme != NULL);
+       ATLASSERT(::IsWindow(hWnd));
+
+       CWindowDC dc(hWnd);
+       if(dc.IsNull())
+               return false;
+
+       // Get border size
+       int cxBorder = GetSystemMetrics(SM_CXBORDER);
+       int cyBorder = GetSystemMetrics(SM_CYBORDER);
+       if(SUCCEEDED(::GetThemeInt(hTheme, nPartID, nStateID, TMT_SIZINGBORDERWIDTH, &cxBorder)))
+               cyBorder = cxBorder;
+
+       RECT rect;
+       ::GetWindowRect(hWnd, &rect);            
+
+       // Remove the client edge from the update region
+       int cxEdge = GetSystemMetrics(SM_CXEDGE);
+       int cyEdge = GetSystemMetrics(SM_CYEDGE);
+       ::InflateRect(&rect, -cxEdge, -cyEdge);
+       CRgn rgn;
+       rgn.CreateRectRgnIndirect(&rect);
+       if(rgn.IsNull())
+               return false;
+
+       if(hRgnUpdate != NULL)
+               rgn.CombineRgn(hRgnUpdate, rgn, RGN_AND);
+
+       ::OffsetRect(&rect, -rect.left, -rect.top);
+
+       ::OffsetRect(&rect, cxEdge, cyEdge);
+       dc.ExcludeClipRect(&rect);
+       ::InflateRect(&rect, cxEdge, cyEdge);
+
+       ::DrawThemeBackground(hTheme, dc, nPartID, nStateID, &rect, NULL);
+
+       // Use background brush too, since theme border might not cover everything
+       if(cxBorder < cxEdge && cyBorder < cyEdge)
+       {
+               if(hBrush == NULL)
+// need conditional code because types don't match in winuser.h
+#ifdef _WIN64
+                       hBrush = (HBRUSH)::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND);
+#else
+                       hBrush = (HBRUSH)UlongToPtr(::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND));
+#endif
+
+               ::InflateRect(&rect, cxBorder - cxEdge, cyBorder - cyEdge);
+               dc.FillRect(&rect, hBrush);
+       }
+
+       ::DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0L);
+
+       return true;
+}
+
+
+// Theme extended styles
+#define THEME_EX_3DCLIENTEDGE          0x00000001
+#define THEME_EX_THEMECLIENTEDGE       0x00000002
+
+template <class T, class TBase = CTheme>
+class CThemeImpl : public TBase
+{
+public:
+// Data members
+       LPWSTR m_lpstrThemeClassList;
+       DWORD m_dwExtendedStyle;   // theme specific extended styles
+
+// Constructor & destructor
+       CThemeImpl() : m_lpstrThemeClassList(NULL), m_dwExtendedStyle(0)
+       { }
+
+       ~CThemeImpl()
+       {
+               delete [] m_lpstrThemeClassList;
+       }
+
+// Attributes
+       bool SetThemeClassList(LPCWSTR lpstrThemeClassList)
+       {
+               if(m_lpstrThemeClassList != NULL)
+               {
+                       delete [] m_lpstrThemeClassList;
+                       m_lpstrThemeClassList = NULL;
+               }
+
+               if(lpstrThemeClassList == NULL)
+                       return true;
+
+               int cchLen = lstrlenW(lpstrThemeClassList) + 1;
+               ATLTRY(m_lpstrThemeClassList = new WCHAR[cchLen]);
+               if(m_lpstrThemeClassList == NULL)
+                       return false;
+
+               SecureHelper::strcpyW_x(m_lpstrThemeClassList, cchLen, lpstrThemeClassList);
+
+               return true;
+       }
+
+       bool GetThemeClassList(LPWSTR lpstrThemeClassList, int cchListBuffer) const
+       {
+               int cchLen = lstrlenW(m_lpstrThemeClassList) + 1;
+               if(cchListBuffer < cchLen)
+                       return false;
+
+               SecureHelper::strcpyW_x(lpstrThemeClassList, cchListBuffer, m_lpstrThemeClassList);
+
+               return true;
+       }
+
+       LPCWSTR GetThemeClassList() const
+       {
+               return m_lpstrThemeClassList;
+       }
+
+       DWORD SetThemeExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
+       {
+               DWORD dwPrevStyle = m_dwExtendedStyle;
+               if(dwMask == 0)
+                       m_dwExtendedStyle = dwExtendedStyle;
+               else
+                       m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
+               return dwPrevStyle;
+       }
+
+       DWORD GetThemeExtendedStyle() const
+       {
+               return m_dwExtendedStyle;
+       }
+
+// Operations
+       HTHEME OpenThemeData()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               ATLASSERT(m_lpstrThemeClassList != NULL);
+               if(m_lpstrThemeClassList == NULL)
+                       return NULL;
+               CloseThemeData();
+               return TBase::OpenThemeData(pT->m_hWnd, m_lpstrThemeClassList);
+       }
+
+       HTHEME OpenThemeData(LPCWSTR pszClassList)
+       {
+               if(!SetThemeClassList(pszClassList))
+                       return NULL;
+               return OpenThemeData();
+       }
+
+       HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIDList)
+       {
+               if(!IsThemingSupported())
+                       return S_FALSE;
+
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::SetWindowTheme(pT->m_hWnd, pszSubAppName, pszSubIDList);
+       }
+
+       HTHEME GetWindowTheme() const
+       {
+               if(!IsThemingSupported())
+                       return NULL;
+
+               const T* pT = static_cast<const T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::GetWindowTheme(pT->m_hWnd);
+       }
+
+       HRESULT EnableThemeDialogTexture(DWORD dwFlags)
+       {
+               if(!IsThemingSupported())
+                       return S_FALSE;
+
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::EnableThemeDialogTexture(pT->m_hWnd, dwFlags);
+       }
+
+       BOOL IsThemeDialogTextureEnabled() const
+       {
+               if(!IsThemingSupported())
+                       return FALSE;
+
+               const T* pT = static_cast<const T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::IsThemeDialogTextureEnabled(pT->m_hWnd);
+       }
+
+       HRESULT DrawThemeParentBackground(HDC hDC, const RECT* pRect = NULL)
+       {
+               if(!IsThemingSupported())
+                       return S_FALSE;
+
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+#ifdef _WTL_NEW_UXTHEME
+               return ::DrawThemeParentBackground(pT->m_hWnd, hDC, pRect);
+#else
+               return ::DrawThemeParentBackground(pT->m_hWnd, hDC, (RECT*)pRect);
+#endif
+       }
+
+#ifdef _WTL_NEW_UXTHEME
+       HRESULT SetWindowThemeAttribute(WINDOWTHEMEATTRIBUTETYPE type, PVOID pvAttribute, DWORD cbAttribute)
+       {
+               if(!IsThemingSupported())
+                       return S_FALSE;
+
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::SetWindowThemeAttribute(pT->m_hWnd, type, pvAttribute, cbAttribute);
+       }
+
+       HRESULT SetWindowThemeNonClientAttributes(DWORD dwAttributes, DWORD dwMask)
+       {
+               if(!IsThemingSupported())
+                       return S_FALSE;
+
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               WTA_OPTIONS opt = { dwAttributes, dwMask };
+               return ::SetWindowThemeAttribute(pT->m_hWnd, WTA_NONCLIENT, (PVOID)&opt, sizeof(opt));
+       }
+
+       HRESULT DrawThemeParentBackgroundEx(HDC hDC, DWORD dwFlags, const RECT* lpRect = NULL)
+       {
+               if(!IsThemingSupported())
+                       return S_FALSE;
+
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               return ::DrawThemeParentBackgroundEx(pT->m_hWnd, hDC, dwFlags, lpRect);
+       }
+#endif // _WTL_NEW_UXTHEME
+
+// Message map and handlers
+       // Note: If you handle any of these messages in your derived class,
+       // it is better to put CHAIN_MSG_MAP at the start of your message map.
+       BEGIN_MSG_MAP(CThemeImpl)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
+               MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_lpstrThemeClassList != NULL)
+                       OpenThemeData();
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               CloseThemeData();
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               CloseThemeData();
+               if(m_lpstrThemeClassList != NULL)
+                       OpenThemeData();
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               LRESULT lRet = 0;
+               bHandled = FALSE;
+               if(IsThemingSupported() && ((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0))
+               {
+                       if((m_dwExtendedStyle & THEME_EX_3DCLIENTEDGE) != 0)
+                       {
+                               lRet = ::DefWindowProc(pT->m_hWnd, uMsg, wParam, lParam);
+                               bHandled = TRUE;
+                       }
+                       else if((m_hTheme != NULL) && ((m_dwExtendedStyle & THEME_EX_THEMECLIENTEDGE) != 0))
+                       {
+                               HRGN hRgn = (wParam != 1) ? (HRGN)wParam : NULL;
+                               if(pT->DrawThemeClientEdge(hRgn))
+                                       bHandled = TRUE;
+                       }
+               }
+               return lRet;
+       }
+
+// Drawing helper
+       bool DrawThemeClientEdge(HRGN hRgnUpdate)
+       {
+               T* pT = static_cast<T*>(this);
+               return AtlDrawThemeClientEdge(m_hTheme, pT->m_hWnd, hRgnUpdate, NULL, 0, 0);
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Buffered Paint and Animation
+
+#ifdef _WTL_NEW_UXTHEME
+
+///////////////////////////////////////////////////////////////////////////////
+// CBufferedPaintBase - Buffered Paint support for othe classes
+
+class CBufferedPaintBase
+{
+public:
+       static int m_nIsBufferedPaintSupported;
+
+       CBufferedPaintBase()
+       {
+               if(IsBufferedPaintSupported())
+                       ATLVERIFY(SUCCEEDED(::BufferedPaintInit()));
+       }
+
+       ~CBufferedPaintBase()
+       {
+               if(IsBufferedPaintSupported())
+                       ATLVERIFY(SUCCEEDED(::BufferedPaintUnInit()));
+       }
+
+       static bool IsBufferedPaintSupported()
+       {
+               if(m_nIsBufferedPaintSupported == -1)
+               {
+                       CStaticDataInitCriticalSectionLock lock;
+                       if(FAILED(lock.Lock()))
+                       {
+                               ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CBufferedPaintBase::IsBufferedPaintSupported.\n"));
+                               ATLASSERT(FALSE);
+                               return false;
+                       }
+
+                       if(m_nIsBufferedPaintSupported == -1)
+                               m_nIsBufferedPaintSupported = RunTimeHelper::IsVista() ? 1 : 0;
+
+                       lock.Unlock();
+               }
+
+               ATLASSERT(m_nIsBufferedPaintSupported != -1);
+               return (m_nIsBufferedPaintSupported == 1);
+       }
+};
+
+__declspec(selectany) int CBufferedPaintBase::m_nIsBufferedPaintSupported = -1;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CBufferedPaint - support for buffered paint functions
+
+class CBufferedPaint
+{
+public:
+       HPAINTBUFFER m_hPaintBuffer;
+
+       CBufferedPaint() : m_hPaintBuffer(NULL)
+       { }
+
+       ~CBufferedPaint()
+       {
+               ATLVERIFY(SUCCEEDED(End()));
+       }
+
+       bool IsNull() const
+       {
+               return (m_hPaintBuffer == NULL);
+       }
+
+       HPAINTBUFFER Begin(HDC hdcTarget, const RECT* prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, HDC* phdcPaint)
+       {
+               ATLASSERT(m_hPaintBuffer == NULL);
+               m_hPaintBuffer = ::BeginBufferedPaint(hdcTarget, prcTarget, dwFormat, pPaintParams, phdcPaint);
+               return m_hPaintBuffer;
+       }
+
+       HRESULT End(BOOL bUpdate = TRUE)
+       {
+               HRESULT hRet = S_FALSE;
+               if(m_hPaintBuffer != NULL)
+               {
+                       hRet = ::EndBufferedPaint(m_hPaintBuffer, bUpdate);
+                       m_hPaintBuffer = NULL;
+               }
+               return hRet;
+       }
+
+       HRESULT GetTargetRect(LPRECT pRect) const
+       {
+               ATLASSERT(m_hPaintBuffer != NULL);
+               return ::GetBufferedPaintTargetRect(m_hPaintBuffer, pRect);
+       }
+
+       HDC GetTargetDC() const
+       {
+               ATLASSERT(m_hPaintBuffer != NULL);
+               return ::GetBufferedPaintTargetDC(m_hPaintBuffer);
+       }
+
+       HDC GetPaintDC() const
+       {
+               ATLASSERT(m_hPaintBuffer != NULL);
+               return ::GetBufferedPaintDC(m_hPaintBuffer);
+       }
+
+       HRESULT GetBits(RGBQUAD** ppbBuffer, int* pcxRow) const
+       {
+               ATLASSERT(m_hPaintBuffer != NULL);
+               return ::GetBufferedPaintBits(m_hPaintBuffer, ppbBuffer, pcxRow);
+       }
+
+       HRESULT Clear(const RECT* pRect = NULL)
+       {
+               ATLASSERT(m_hPaintBuffer != NULL);
+               return ::BufferedPaintClear(m_hPaintBuffer, pRect);
+       }
+
+       HRESULT SetAlpha(BYTE alpha, const RECT* pRect = NULL)
+       {
+               ATLASSERT(m_hPaintBuffer != NULL);
+               return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, alpha);
+       }
+
+       HRESULT MakeOpaque(const RECT* pRect = NULL)
+       {
+               ATLASSERT(m_hPaintBuffer != NULL);
+               return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, 255);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CBufferedPaintImpl - provides buffered paint for any window
+
+template <class T>
+class ATL_NO_VTABLE CBufferedPaintImpl : public CBufferedPaintBase
+{
+public:
+       CBufferedPaint m_BufferedPaint;
+       BP_BUFFERFORMAT m_dwFormat;
+       BP_PAINTPARAMS m_PaintParams;
+
+       CBufferedPaintImpl() : m_dwFormat(BPBF_TOPDOWNDIB)
+       {
+               memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS));
+               m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS);
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CBufferedPaintImpl)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+       END_MSG_MAP()
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;   // no background needed
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               if(wParam != NULL)
+               {
+                       RECT rect = { 0 };
+                       pT->GetClientRect(&rect);
+                       pT->DoPaint((HDC)wParam, rect);
+               }
+               else
+               {
+                       CPaintDC dc(pT->m_hWnd);
+                       pT->DoBufferedPaint(dc.m_hDC, dc.m_ps.rcPaint);
+               }
+
+               return 0;
+       }
+
+// Overrideables
+       void DoBufferedPaint(CDCHandle dc, RECT& rect)
+       {
+               HDC hDCPaint = NULL;
+               if(IsBufferedPaintSupported())
+                       m_BufferedPaint.Begin(dc, &rect, m_dwFormat, &m_PaintParams, &hDCPaint);
+
+               T* pT = static_cast<T*>(this);
+               if(hDCPaint != NULL)
+                       pT->DoPaint(hDCPaint, rect);
+               else
+                       pT->DoPaint(dc.m_hDC, rect);
+
+               if(IsBufferedPaintSupported())
+                       m_BufferedPaint.End();
+       }
+
+       void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/)
+       {
+               // must be implemented in a derived class
+               ATLASSERT(FALSE);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CBufferedPaintWindowImpl - implements a window that uses buffered paint
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CBufferedPaintWindowImpl : 
+               public ATL::CWindowImpl<T, TBase, TWinTraits>, 
+               public CBufferedPaintImpl< T >
+{
+public:
+       BEGIN_MSG_MAP(CBufferedPaintWindowImpl)
+               CHAIN_MSG_MAP(CBufferedPaintImpl< T >)
+       END_MSG_MAP()
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CBufferedAnimation - support for buffered animation
+
+class CBufferedAnimation
+{
+public:
+       HANIMATIONBUFFER m_hAnimationBuffer;
+
+       CBufferedAnimation() : m_hAnimationBuffer(NULL)
+       { }
+
+       ~CBufferedAnimation()
+       {
+               ATLVERIFY(SUCCEEDED(End()));
+       }
+
+       bool IsNull() const
+       {
+               return (m_hAnimationBuffer == NULL);
+       }
+
+       HANIMATIONBUFFER Begin(HWND hWnd, HDC hDCTarget, const RECT* pRectTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, BP_ANIMATIONPARAMS* pAnimationParams, HDC* phdcFrom, HDC* phdcTo)
+       {
+               ATLASSERT(m_hAnimationBuffer == NULL);
+               m_hAnimationBuffer = ::BeginBufferedAnimation(hWnd, hDCTarget, pRectTarget, dwFormat, pPaintParams, pAnimationParams, phdcFrom, phdcTo);
+               return m_hAnimationBuffer;
+       }
+
+       HRESULT End(BOOL bUpdate = TRUE)
+       {
+               HRESULT hRet = S_FALSE;
+               if(m_hAnimationBuffer != NULL)
+               {
+                       hRet = ::EndBufferedAnimation(m_hAnimationBuffer, bUpdate);
+                       m_hAnimationBuffer = NULL;
+               }
+               return hRet;
+       }
+
+       static bool IsRendering(HWND hWnd, HDC hDC)
+       {
+               return (::BufferedPaintRenderAnimation(hWnd, hDC) != FALSE);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CBufferedAnimationImpl - provides buffered animation support for any window
+
+// Note: You can either use m_State and m_NewState to store the state information
+// for the animation change, or map your state to those data members. DoPaint()
+// should only rely on the state information that is passed to it.
+
+template <class T, class TState = DWORD_PTR>
+class ATL_NO_VTABLE CBufferedAnimationImpl : public CBufferedPaintBase
+{
+public:
+       BP_BUFFERFORMAT m_dwFormat;
+       BP_PAINTPARAMS m_PaintParams;
+       BP_ANIMATIONPARAMS m_AnimationParams;
+
+       TState m_State;
+       TState m_NewState;
+
+       CBufferedAnimationImpl(TState InitialState) : m_dwFormat(BPBF_TOPDOWNDIB)
+       {
+               memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS));
+               m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS);
+
+               memset(&m_AnimationParams, 0, sizeof(BP_ANIMATIONPARAMS));
+               m_AnimationParams.cbSize = sizeof(BP_ANIMATIONPARAMS);
+               m_AnimationParams.style = BPAS_LINEAR;
+               m_AnimationParams.dwDuration = 500;
+
+               T* pT = static_cast<T*>(this);
+               pT->SetState(InitialState);
+               pT->SetNewState(InitialState);
+       }
+
+       DWORD GetDuration() const
+       {
+               return m_AnimationParams.dwDuration;
+       }
+
+       void SetDuration(DWORD dwDuration)
+       {
+               m_AnimationParams.dwDuration = dwDuration;
+       }
+
+       void DoAnimation(TState NewState, const RECT* pRect = NULL)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->SetNewState(NewState);
+
+               pT->InvalidateRect(pRect, FALSE);
+               pT->UpdateWindow();
+
+               pT->SetState(NewState);
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CBufferedAnimationImpl)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+       END_MSG_MAP()
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return 1;   // no background needed
+       }
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               if(wParam != NULL)
+               {
+                       RECT rect = { 0 };
+                       pT->GetClientRect(&rect);
+                       pT->DoPaint((HDC)wParam, rect, m_NewState);
+               }
+               else
+               {
+                       CPaintDC dc(pT->m_hWnd);
+                       pT->DoAnimationPaint(dc.m_hDC, dc.m_ps.rcPaint);
+               }
+
+               return 0;
+       }
+
+// Overrideables
+       void SetState(TState State)
+       {
+               m_State = State;
+       }
+
+       void SetNewState(TState State)
+       {
+               m_NewState = State;
+       }
+
+       bool AreStatesEqual() const
+       {
+               return (m_State == m_NewState);
+       }
+
+       void DoAnimationPaint(CDCHandle dc, RECT& rect)
+       {
+               T* pT = static_cast<T*>(this);
+               if(IsBufferedPaintSupported() && CBufferedAnimation::IsRendering(pT->m_hWnd, dc))
+                       return;
+
+               DWORD dwDurationSave = m_AnimationParams.dwDuration;
+               if(pT->AreStatesEqual())
+                       m_AnimationParams.dwDuration = 0;
+
+               HDC hdcFrom = NULL, hdcTo = NULL;
+               CBufferedAnimation ba;
+               if(IsBufferedPaintSupported())
+                       ba.Begin(pT->m_hWnd, dc, &rect, m_dwFormat, &m_PaintParams, &m_AnimationParams, &hdcFrom, &hdcTo);
+
+               if(!ba.IsNull())
+               {
+                       if(hdcFrom != NULL)
+                               pT->DoPaint(hdcFrom, rect, m_State);
+
+                       if (hdcTo != NULL)
+                               pT->DoPaint(hdcTo, rect, m_NewState);
+               }
+               else
+               {
+                       pT->DoPaint(dc.m_hDC, rect, m_NewState);
+               }
+
+               m_AnimationParams.dwDuration = dwDurationSave;
+       }
+
+       void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/, TState /*State*/)
+       {
+               // must be implemented in a derived class
+               ATLASSERT(FALSE);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CBufferedAnimationWindowImpl - implements a window that uses buffered animation
+
+template <class T, class TState = DWORD_PTR, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CBufferedAnimationWindowImpl : 
+               public ATL::CWindowImpl<T, TBase, TWinTraits>, 
+               public CBufferedAnimationImpl< T, TState >
+{
+public:
+       CBufferedAnimationWindowImpl(TState InitialState) : CBufferedAnimationImpl< T, TState >(InitialState)
+       { }
+
+       typedef CBufferedAnimationImpl< T, TState >   _baseBufferedAnimation;
+       BEGIN_MSG_MAP(CBufferedAnimationWindowImpl)
+               CHAIN_MSG_MAP(_baseBufferedAnimation)
+       END_MSG_MAP()
+};
+
+#endif // _WTL_NEW_UXTHEME
+
+}; // namespace WTL
+
+#endif // __ATLTHEME_H__
diff --git a/include/WTL/Include/atluser.h b/include/WTL/Include/atluser.h
new file mode 100644 (file)
index 0000000..a056c9b
--- /dev/null
@@ -0,0 +1,1193 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLUSER_H__
+#define __ATLUSER_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atluser.h requires atlapp.h to be included first
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CMenuItemInfo
+// CMenuT<t_bManaged>
+// CAcceleratorT<t_bManaged>
+// CIconT<t_bManaged>
+// CCursorT<t_bManaged>
+// CResource
+//
+// Global functions:
+//   AtlMessageBox()
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// AtlMessageBox - accepts both memory and resource based strings
+
+inline int AtlMessageBox(HWND hWndOwner, ATL::_U_STRINGorID message, ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uType = MB_OK | MB_ICONINFORMATION)
+{
+       ATLASSERT(hWndOwner == NULL || ::IsWindow(hWndOwner));
+
+       LPTSTR lpstrMessage = NULL;
+       if(IS_INTRESOURCE(message.m_lpstr))
+       {
+               for(int nLen = 256; ; nLen *= 2)
+               {
+                       ATLTRY(lpstrMessage = new TCHAR[nLen]);
+                       if(lpstrMessage == NULL)
+                       {
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+                       int nRes = ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(message.m_lpstr), lpstrMessage, nLen);
+                       if(nRes < nLen - 1)
+                               break;
+                       delete [] lpstrMessage;
+                       lpstrMessage = NULL;
+               }
+
+               message.m_lpstr = lpstrMessage;
+       }
+
+       LPTSTR lpstrTitle = NULL;
+       if(IS_INTRESOURCE(title.m_lpstr) && LOWORD(title.m_lpstr) != 0)
+       {
+               for(int nLen = 256; ; nLen *= 2)
+               {
+                       ATLTRY(lpstrTitle = new TCHAR[nLen]);
+                       if(lpstrTitle == NULL)
+                       {
+                               ATLASSERT(FALSE);
+                               return 0;
+                       }
+                       int nRes = ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(title.m_lpstr), lpstrTitle, nLen);
+                       if(nRes < nLen - 1)
+                               break;
+                       delete [] lpstrTitle;
+                       lpstrTitle = NULL;
+               }
+
+               title.m_lpstr = lpstrTitle;
+       }
+
+       int nRet = ::MessageBox(hWndOwner, message.m_lpstr, title.m_lpstr, uType);
+
+       delete [] lpstrMessage;
+       delete [] lpstrTitle;
+
+       return nRet;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CMenu
+
+#if (WINVER >= 0x0500)
+  #ifndef MII_SIZEOF_STRUCT
+    #define MII_SIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
+  #endif
+  #define MENUITEMINFO_SIZE_VERSION_400A  MII_SIZEOF_STRUCT(MENUITEMINFOA, cch)
+  #define MENUITEMINFO_SIZE_VERSION_400W  MII_SIZEOF_STRUCT(MENUITEMINFOW, cch)
+  #ifdef UNICODE
+    #define MENUITEMINFO_SIZE_VERSION_400  MENUITEMINFO_SIZE_VERSION_400W
+  #else
+    #define MENUITEMINFO_SIZE_VERSION_400  MENUITEMINFO_SIZE_VERSION_400A
+  #endif // !UNICODE
+#endif // (WINVER >= 0x0500)
+
+class CMenuItemInfo : public MENUITEMINFO
+{
+public:
+       CMenuItemInfo()
+       {
+               memset(this, 0, sizeof(MENUITEMINFO));
+               cbSize = sizeof(MENUITEMINFO);
+#if (WINVER >= 0x0500)
+               // adjust struct size if running on older version of Windows
+               if(AtlIsOldWindows())
+               {
+                       ATLASSERT(cbSize > MENUITEMINFO_SIZE_VERSION_400);   // must be
+                       cbSize = MENUITEMINFO_SIZE_VERSION_400;
+               }
+#endif // (WINVER >= 0x0500)
+       }
+};
+
+
+// forward declarations
+template <bool t_bManaged> class CMenuT;
+typedef CMenuT<false>   CMenuHandle;
+typedef CMenuT<true>    CMenu;
+
+
+template <bool t_bManaged>
+class CMenuT
+{
+public:
+// Data members
+       HMENU m_hMenu;
+
+// Constructor/destructor/operators
+       CMenuT(HMENU hMenu = NULL) : m_hMenu(hMenu)
+       { }
+
+       ~CMenuT()
+       {
+               if(t_bManaged && m_hMenu != NULL)
+                       DestroyMenu();
+       }
+
+       CMenuT<t_bManaged>& operator =(HMENU hMenu)
+       {
+               Attach(hMenu);
+               return *this;
+       }
+
+       void Attach(HMENU hMenuNew)
+       {
+               ATLASSERT(::IsMenu(hMenuNew));
+               if(t_bManaged && m_hMenu != NULL && m_hMenu != hMenuNew)
+                       ::DestroyMenu(m_hMenu);
+               m_hMenu = hMenuNew;
+       }
+
+       HMENU Detach()
+       {
+               HMENU hMenu = m_hMenu;
+               m_hMenu = NULL;
+               return hMenu;
+       }
+
+       operator HMENU() const { return m_hMenu; }
+
+       bool IsNull() const { return (m_hMenu == NULL); }
+
+       BOOL IsMenu() const
+       {
+               return ::IsMenu(m_hMenu);
+       }
+
+// Create/destroy methods
+       BOOL CreateMenu()
+       {
+               ATLASSERT(m_hMenu == NULL);
+               m_hMenu = ::CreateMenu();
+               return (m_hMenu != NULL) ? TRUE : FALSE;
+       }
+
+       BOOL CreatePopupMenu()
+       {
+               ATLASSERT(m_hMenu == NULL);
+               m_hMenu = ::CreatePopupMenu();
+               return (m_hMenu != NULL) ? TRUE : FALSE;
+       }
+
+       BOOL LoadMenu(ATL::_U_STRINGorID menu)
+       {
+               ATLASSERT(m_hMenu == NULL);
+               m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr);
+               return (m_hMenu != NULL) ? TRUE : FALSE;
+       }
+
+#ifndef _WIN32_WCE
+       BOOL LoadMenuIndirect(const void* lpMenuTemplate)
+       {
+               ATLASSERT(m_hMenu == NULL);
+               m_hMenu = ::LoadMenuIndirect(lpMenuTemplate);
+               return (m_hMenu != NULL) ? TRUE : FALSE;
+       }
+#endif // !_WIN32_WCE
+
+       BOOL DestroyMenu()
+       {
+               if (m_hMenu == NULL)
+                       return FALSE;
+               BOOL bRet = ::DestroyMenu(m_hMenu);
+               if(bRet)
+                       m_hMenu = NULL;
+               return bRet;
+       }
+
+// Menu Operations
+       BOOL DeleteMenu(UINT nPosition, UINT nFlags)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::DeleteMenu(m_hMenu, nPosition, nFlags);
+       }
+
+       BOOL TrackPopupMenu(UINT nFlags, int x, int y, HWND hWnd, LPCRECT lpRect = NULL)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+#ifndef _WIN32_WCE
+#if (WINVER >= 0x0500)
+               x = _FixTrackMenuPopupX(x, y);
+#endif // !(WINVER >= 0x0500)
+               return ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0, hWnd, lpRect);
+#else // CE specific
+               lpRect;
+               return ::TrackPopupMenuEx(m_hMenu, nFlags, x, y, hWnd, NULL);
+#endif // _WIN32_WCE
+       }
+
+       BOOL TrackPopupMenuEx(UINT uFlags, int x, int y, HWND hWnd, LPTPMPARAMS lptpm = NULL)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+               x = _FixTrackMenuPopupX(x, y);
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+               return ::TrackPopupMenuEx(m_hMenu, uFlags, x, y, hWnd, lptpm);
+       }
+
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+       // helper that fixes popup menu X position when it's off-screen
+       static int _FixTrackMenuPopupX(int x, int y)
+       {
+               POINT pt = { x, y };
+               HMONITOR hMonitor = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
+               if(hMonitor == NULL)
+               {
+                       HMONITOR hMonitorNear = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
+                       if(hMonitorNear != NULL)
+                       {
+                               MONITORINFO mi = { 0 };
+                               mi.cbSize = sizeof(MONITORINFO);
+                               if(::GetMonitorInfo(hMonitorNear, &mi) != FALSE)
+                               {
+                                       if(x < mi.rcWork.left)
+                                               x = mi.rcWork.left;
+                                       else if(x > mi.rcWork.right)
+                                               x = mi.rcWork.right;
+                               }
+                       }
+               }
+
+               return x;
+       }
+
+       BOOL GetMenuInfo(LPMENUINFO lpMenuInfo) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuInfo(m_hMenu, lpMenuInfo);
+       }
+
+       BOOL SetMenuInfo(LPCMENUINFO lpMenuInfo)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::SetMenuInfo(m_hMenu, lpMenuInfo);
+       }
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+
+// Menu Item Operations
+       BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::AppendMenu(m_hMenu, nFlags, nIDNewItem, lpszNewItem);
+       }
+
+       BOOL AppendMenu(UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               ATLASSERT(::IsMenu(hSubMenu));
+               return ::AppendMenu(m_hMenu, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::AppendMenu(m_hMenu, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp);
+       }
+
+       BOOL AppendMenu(UINT nFlags, HMENU hSubMenu, HBITMAP hBmp)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               ATLASSERT(::IsMenu(hSubMenu));
+               return ::AppendMenu(m_hMenu, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp);
+       }
+#endif // !_WIN32_WCE
+
+       UINT CheckMenuItem(UINT nIDCheckItem, UINT nCheck)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return (UINT)::CheckMenuItem(m_hMenu, nIDCheckItem, nCheck);
+       }
+
+       UINT EnableMenuItem(UINT nIDEnableItem, UINT nEnable)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::EnableMenuItem(m_hMenu, nIDEnableItem, nEnable);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL HiliteMenuItem(HWND hWnd, UINT uIDHiliteItem, UINT uHilite)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::HiliteMenuItem(hWnd, m_hMenu, uIDHiliteItem, uHilite);
+       }
+
+       int GetMenuItemCount() const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuItemCount(m_hMenu);
+       }
+
+       UINT GetMenuItemID(int nPos) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuItemID(m_hMenu, nPos);
+       }
+
+       UINT GetMenuState(UINT nID, UINT nFlags) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuState(m_hMenu, nID, nFlags);
+       }
+
+       int GetMenuString(UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuString(m_hMenu, nIDItem, lpString, nMaxCount, nFlags);
+       }
+
+       int GetMenuStringLen(UINT nIDItem, UINT nFlags) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuString(m_hMenu, nIDItem, NULL, 0, nFlags);
+       }
+
+#ifndef _ATL_NO_COM
+       BOOL GetMenuString(UINT nIDItem, BSTR& bstrText, UINT nFlags) const
+       {
+               USES_CONVERSION;
+               ATLASSERT(::IsMenu(m_hMenu));
+               ATLASSERT(bstrText == NULL);
+
+               int nLen = GetMenuStringLen(nIDItem, nFlags);
+               if(nLen == 0)
+               {
+                       bstrText = ::SysAllocString(OLESTR(""));
+                       return (bstrText != NULL) ? TRUE : FALSE;
+               }
+
+               nLen++;   // increment to include terminating NULL char
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR lpszText = buff.Allocate(nLen);
+               if(lpszText == NULL)
+                       return FALSE;
+
+               if(!GetMenuString(nIDItem, lpszText, nLen, nFlags))
+                       return FALSE;
+
+               bstrText = ::SysAllocString(T2OLE(lpszText));
+               return (bstrText != NULL) ? TRUE : FALSE;
+       }
+#endif // !_ATL_NO_COM
+
+#elif _ATL_VER >= 0x800
+       int GetMenuItemCount() const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ATL::GetMenuItemCount(m_hMenu);
+       }
+
+       UINT GetMenuItemID(int nPos) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ATL::GetMenuItemID(m_hMenu, nPos);
+       }
+
+       UINT GetMenuState(UINT nID, UINT nFlags) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ATL::GetMenuState(m_hMenu, nID, nFlags);
+       }
+
+       int GetMenuString(UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ATL::GetMenuString(m_hMenu, nIDItem, lpString, nMaxCount, nFlags);
+       }
+
+       int GetMenuStringLen(UINT nIDItem, UINT nFlags) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ATL::GetMenuString(m_hMenu, nIDItem, NULL, 0, nFlags);
+       }
+#endif // _ATL_VER >= 0x800
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       int GetMenuString(UINT nIDItem, _CSTRING_NS::CString& strText, UINT nFlags) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+
+               int nLen = GetMenuStringLen(nIDItem, nFlags);
+               if(nLen == 0)
+                       return 0;
+
+               nLen++;   // increment to include terminating NULL char
+               LPTSTR lpstr = strText.GetBufferSetLength(nLen);
+               if(lpstr == NULL)
+                       return 0;
+               int nRet = GetMenuString(nIDItem, lpstr, nLen, nFlags);
+               strText.ReleaseBuffer();
+               return nRet;
+       }
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+
+       CMenuHandle GetSubMenu(int nPos) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return CMenuHandle(::GetSubMenu(m_hMenu, nPos));
+       }
+
+       BOOL InsertMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::InsertMenu(m_hMenu, nPosition, nFlags, nIDNewItem, lpszNewItem);
+       }
+
+       BOOL InsertMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               ATLASSERT(::IsMenu(hSubMenu));
+               return ::InsertMenu(m_hMenu, nPosition, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL InsertMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::InsertMenu(m_hMenu, nPosition, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp);
+       }
+
+       BOOL InsertMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, HBITMAP hBmp)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               ATLASSERT(::IsMenu(hSubMenu));
+               return ::InsertMenu(m_hMenu, nPosition, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp);
+       }
+
+       BOOL ModifyMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::ModifyMenu(m_hMenu, nPosition, nFlags, nIDNewItem, lpszNewItem);
+       }
+
+       BOOL ModifyMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               ATLASSERT(::IsMenu(hSubMenu));
+               return ::ModifyMenu(m_hMenu, nPosition, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem);
+       }
+
+       BOOL ModifyMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::ModifyMenu(m_hMenu, nPosition, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp);
+       }
+
+       BOOL ModifyMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, HBITMAP hBmp)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               ATLASSERT(::IsMenu(hSubMenu));
+               return ::ModifyMenu(m_hMenu, nPosition, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL RemoveMenu(UINT nPosition, UINT nFlags)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::RemoveMenu(m_hMenu, nPosition, nFlags);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL SetMenuItemBitmaps(UINT nPosition, UINT nFlags, HBITMAP hBmpUnchecked, HBITMAP hBmpChecked)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::SetMenuItemBitmaps(m_hMenu, nPosition, nFlags, hBmpUnchecked, hBmpChecked);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL CheckMenuRadioItem(UINT nIDFirst, UINT nIDLast, UINT nIDItem, UINT nFlags)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::CheckMenuRadioItem(m_hMenu, nIDFirst, nIDLast, nIDItem, nFlags);
+       }
+
+       BOOL GetMenuItemInfo(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return (BOOL)::GetMenuItemInfo(m_hMenu, uItem, bByPosition, lpmii);
+       }
+
+       BOOL SetMenuItemInfo(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return (BOOL)::SetMenuItemInfo(m_hMenu, uItem, bByPosition, lpmii);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL InsertMenuItem(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return (BOOL)::InsertMenuItem(m_hMenu, uItem, bByPosition, lpmii);
+       }
+
+       UINT GetMenuDefaultItem(BOOL bByPosition = FALSE, UINT uFlags = 0U) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuDefaultItem(m_hMenu, (UINT)bByPosition, uFlags);
+       }
+
+       BOOL SetMenuDefaultItem(UINT uItem = (UINT)-1,  BOOL bByPosition = FALSE)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::SetMenuDefaultItem(m_hMenu, uItem, (UINT)bByPosition);
+       }
+
+       BOOL GetMenuItemRect(HWND hWnd, UINT uItem, LPRECT lprcItem) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuItemRect(hWnd, m_hMenu, uItem, lprcItem);
+       }
+
+       int MenuItemFromPoint(HWND hWnd, POINT point) const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::MenuItemFromPoint(hWnd, m_hMenu, point);
+       }
+
+// Context Help Functions
+       BOOL SetMenuContextHelpId(DWORD dwContextHelpId)
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::SetMenuContextHelpId(m_hMenu, dwContextHelpId);
+       }
+
+       DWORD GetMenuContextHelpId() const
+       {
+               ATLASSERT(::IsMenu(m_hMenu));
+               return ::GetMenuContextHelpId(m_hMenu);
+       }
+#endif // !_WIN32_WCE
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAccelerator
+
+template <bool t_bManaged>
+class CAcceleratorT
+{
+public:
+       HACCEL m_hAccel;
+
+// Constructor/destructor/operators
+       CAcceleratorT(HACCEL hAccel = NULL) : m_hAccel(hAccel)
+       { }
+
+       ~CAcceleratorT()
+       {
+               if(t_bManaged && m_hAccel != NULL)
+                       ::DestroyAcceleratorTable(m_hAccel);
+       }
+
+       CAcceleratorT<t_bManaged>& operator =(HACCEL hAccel)
+       {
+               Attach(hAccel);
+               return *this;
+       }
+
+       void Attach(HACCEL hAccel)
+       {
+               if(t_bManaged && m_hAccel != NULL)
+                       ::DestroyAcceleratorTable(m_hAccel);
+               m_hAccel = hAccel;
+       }
+
+       HACCEL Detach()
+       {
+               HACCEL hAccel = m_hAccel;
+               m_hAccel = NULL;
+               return hAccel;
+       }
+
+       operator HACCEL() const { return m_hAccel; }
+
+       bool IsNull() const { return m_hAccel == NULL; }
+
+// Create/destroy methods
+       HACCEL LoadAccelerators(ATL::_U_STRINGorID accel)
+       {
+               ATLASSERT(m_hAccel == NULL);
+               m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), accel.m_lpstr);
+               return m_hAccel;
+       }
+
+       HACCEL CreateAcceleratorTable(LPACCEL pAccel, int cEntries)
+       {
+               ATLASSERT(m_hAccel == NULL);
+               ATLASSERT(pAccel != NULL);
+               m_hAccel = ::CreateAcceleratorTable(pAccel, cEntries);
+               return m_hAccel;
+       }
+
+       void DestroyObject()
+       {
+               if(m_hAccel != NULL)
+               {
+                       ::DestroyAcceleratorTable(m_hAccel);
+                       m_hAccel = NULL;
+               }
+       }
+
+// Operations
+#ifndef _WIN32_WCE
+       int CopyAcceleratorTable(LPACCEL lpAccelDst, int cEntries)
+       {
+               ATLASSERT(m_hAccel != NULL);
+               ATLASSERT(lpAccelDst != NULL);
+               return ::CopyAcceleratorTable(m_hAccel, lpAccelDst, cEntries);
+       }
+
+       int GetEntriesCount() const
+       {
+               ATLASSERT(m_hAccel != NULL);
+               return ::CopyAcceleratorTable(m_hAccel, NULL, 0);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL TranslateAccelerator(HWND hWnd, LPMSG pMsg)
+       {
+               ATLASSERT(m_hAccel != NULL);
+               ATLASSERT(::IsWindow(hWnd));
+               ATLASSERT(pMsg != NULL);
+               return ::TranslateAccelerator(hWnd, m_hAccel, pMsg);
+       }
+};
+
+typedef CAcceleratorT<false>   CAcceleratorHandle;
+typedef CAcceleratorT<true>    CAccelerator;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CIcon
+
+template <bool t_bManaged>
+class CIconT
+{
+public:
+       HICON m_hIcon;
+
+// Constructor/destructor/operators
+       CIconT(HICON hIcon = NULL) : m_hIcon(hIcon)
+       { }
+
+       ~CIconT()
+       {
+               if(t_bManaged && m_hIcon != NULL)
+                       ::DestroyIcon(m_hIcon);
+       }
+
+       CIconT<t_bManaged>& operator =(HICON hIcon)
+       {
+               Attach(hIcon);
+               return *this;
+       }
+
+       void Attach(HICON hIcon)
+       {
+               if(t_bManaged && m_hIcon != NULL)
+                       ::DestroyIcon(m_hIcon);
+               m_hIcon = hIcon;
+       }
+
+       HICON Detach()
+       {
+               HICON hIcon = m_hIcon;
+               m_hIcon = NULL;
+               return hIcon;
+       }
+
+       operator HICON() const { return m_hIcon; }
+
+       bool IsNull() const { return m_hIcon == NULL; }
+
+// Create/destroy methods
+       HICON LoadIcon(ATL::_U_STRINGorID icon)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               m_hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr);
+               return m_hIcon;
+       }
+
+       HICON LoadIcon(ATL::_U_STRINGorID icon, int cxDesired, int cyDesired, UINT fuLoad = 0)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               m_hIcon = (HICON) ::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad);
+               return m_hIcon;
+       }
+
+#ifndef _WIN32_WCE
+       HICON LoadOEMIcon(LPCTSTR lpstrIconName)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(IsOEMIcon(lpstrIconName));
+               m_hIcon = ::LoadIcon(NULL, lpstrIconName);
+               return m_hIcon;
+       }
+
+       HICON CreateIcon(int nWidth, int nHeight, BYTE cPlanes, BYTE cBitsPixel, CONST BYTE* lpbANDbits, CONST BYTE *lpbXORbits)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(lpbANDbits != NULL);
+               ATLASSERT(lpbXORbits != NULL);
+               m_hIcon = ::CreateIcon(ModuleHelper::GetResourceInstance(), nWidth, nHeight, cPlanes, cBitsPixel, lpbANDbits, lpbXORbits);
+               return m_hIcon;
+       }
+
+       HICON CreateIconFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(pBits != NULL);
+               m_hIcon = ::CreateIconFromResource(pBits, dwResSize, TRUE, dwVersion);
+               return m_hIcon;
+       }
+
+       HICON CreateIconFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(pbBits != NULL);
+               ATLASSERT(cbBits > 0);
+               m_hIcon = ::CreateIconFromResourceEx(pbBits, cbBits, TRUE, dwVersion, cxDesired, cyDesired, uFlags);
+               return m_hIcon;
+       }
+#endif // !_WIN32_WCE
+
+       HICON CreateIconIndirect(PICONINFO pIconInfo)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(pIconInfo != NULL);
+               m_hIcon = ::CreateIconIndirect(pIconInfo);
+               return m_hIcon;
+       }
+
+#ifndef _WIN32_WCE
+       HICON ExtractIcon(LPCTSTR lpszExeFileName, UINT nIconIndex)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(lpszExeFileName != NULL);
+               m_hIcon = ::ExtractIcon(ModuleHelper::GetModuleInstance(), lpszExeFileName, nIconIndex);
+               return m_hIcon;
+       }
+
+       HICON ExtractAssociatedIcon(HINSTANCE hInst, LPTSTR lpIconPath, LPWORD lpiIcon)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(lpIconPath != NULL);
+               ATLASSERT(lpiIcon != NULL);
+               m_hIcon = ::ExtractAssociatedIcon(hInst, lpIconPath, lpiIcon);
+               return m_hIcon;
+       }
+#endif // !_WIN32_WCE
+
+       BOOL DestroyIcon()
+       {
+               ATLASSERT(m_hIcon != NULL);
+               BOOL bRet = ::DestroyIcon(m_hIcon);
+               if(bRet != FALSE)
+                       m_hIcon = NULL;
+               return bRet;
+       }
+
+// Operations
+#ifndef _WIN32_WCE
+       HICON CopyIcon()
+       {
+               ATLASSERT(m_hIcon != NULL);
+               return ::CopyIcon(m_hIcon);
+       }
+
+       HICON DuplicateIcon()
+       {
+               ATLASSERT(m_hIcon != NULL);
+               return ::DuplicateIcon(NULL, m_hIcon);
+       }
+#endif // !_WIN32_WCE
+
+       BOOL DrawIcon(HDC hDC, int x, int y)
+       {
+               ATLASSERT(m_hIcon != NULL);
+#ifndef _WIN32_WCE
+               return ::DrawIcon(hDC, x, y, m_hIcon);
+#else // CE specific
+               return ::DrawIconEx(hDC, x, y, m_hIcon, 0, 0, 0, NULL, DI_NORMAL);
+#endif // _WIN32_WCE
+       }
+
+       BOOL DrawIcon(HDC hDC, POINT pt)
+       {
+               ATLASSERT(m_hIcon != NULL);
+#ifndef _WIN32_WCE
+               return ::DrawIcon(hDC, pt.x, pt.y, m_hIcon);
+#else // CE specific
+               return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, 0, 0, 0, NULL, DI_NORMAL);
+#endif // _WIN32_WCE
+       }
+
+       BOOL DrawIconEx(HDC hDC, int x, int y, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
+       {
+               ATLASSERT(m_hIcon != NULL);
+               return ::DrawIconEx(hDC, x, y, m_hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
+       }
+
+       BOOL DrawIconEx(HDC hDC, POINT pt, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
+       {
+               ATLASSERT(m_hIcon != NULL);
+               return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
+       }
+
+#ifndef _WIN32_WCE
+       BOOL GetIconInfo(PICONINFO pIconInfo) const
+       {
+               ATLASSERT(m_hIcon != NULL);
+               ATLASSERT(pIconInfo != NULL);
+               return ::GetIconInfo(m_hIcon, pIconInfo);
+       }
+
+#if (_WIN32_WINNT >= 0x0600)
+       BOOL GetIconInfoEx(PICONINFOEX pIconInfo) const
+       {
+               ATLASSERT(m_hIcon != NULL);
+               ATLASSERT(pIconInfo != NULL);
+               return ::GetIconInfoEx(m_hIcon, pIconInfo);
+       }
+#endif // (_WIN32_WINNT >= 0x0600)
+
+#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+       HRESULT LoadIconMetric(ATL::_U_STRINGorID icon, int lims)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               USES_CONVERSION;
+               return ::LoadIconMetric(ModuleHelper::GetResourceInstance(), T2CW(icon.m_lpstr), lims, &m_hIcon);
+       }
+
+       HRESULT LoadIconWithScaleDown(ATL::_U_STRINGorID icon, int cx, int cy)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               USES_CONVERSION;
+               return ::LoadIconWithScaleDown(ModuleHelper::GetResourceInstance(), T2CW(icon.m_lpstr), cx, cy, &m_hIcon);
+       }
+
+       HRESULT LoadOEMIconMetric(LPCTSTR lpstrIconName, int lims)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(IsOEMIcon(lpstrIconName));
+               return ::LoadIconMetric(NULL, (LPCWSTR)lpstrIconName, lims, &m_hIcon);
+       }
+
+       HRESULT LoadOEMIconWithScaleDown(LPCTSTR lpstrIconName, int cx, int cy)
+       {
+               ATLASSERT(m_hIcon == NULL);
+               ATLASSERT(IsOEMIcon(lpstrIconName));
+               USES_CONVERSION;
+               return ::LoadIconWithScaleDown(NULL, (LPCWSTR)lpstrIconName, cx, cy, &m_hIcon);
+       }
+#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
+#endif // !_WIN32_WCE
+
+       // Helper
+#ifndef _WIN32_WCE
+       static bool IsOEMIcon(LPCTSTR lpstrIconName)
+       {
+#if (WINVER >= 0x0600)
+               return (lpstrIconName == IDI_APPLICATION || lpstrIconName == IDI_ASTERISK || lpstrIconName == IDI_EXCLAMATION ||
+                         lpstrIconName == IDI_HAND || lpstrIconName == IDI_QUESTION || lpstrIconName == IDI_WINLOGO ||
+                         lpstrIconName == IDI_SHIELD);
+#else // !(WINVER >= 0x0600)
+               return (lpstrIconName == IDI_APPLICATION || lpstrIconName == IDI_ASTERISK || lpstrIconName == IDI_EXCLAMATION ||
+                         lpstrIconName == IDI_HAND || lpstrIconName == IDI_QUESTION || lpstrIconName == IDI_WINLOGO);
+#endif // !(WINVER >= 0x0600)
+       }
+#endif // !_WIN32_WCE
+};
+
+typedef CIconT<false>   CIconHandle;
+typedef CIconT<true>    CIcon;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CCursor
+
+// protect template member from a winuser.h macro
+#ifdef CopyCursor
+  #undef CopyCursor
+#endif
+
+template <bool t_bManaged>
+class CCursorT
+{
+public:
+       HCURSOR m_hCursor;
+
+// Constructor/destructor/operators
+       CCursorT(HCURSOR hCursor = NULL) : m_hCursor(hCursor)
+       { }
+
+       ~CCursorT()
+       {
+               if(t_bManaged && m_hCursor != NULL)
+                       DestroyCursor();
+       }
+
+       CCursorT<t_bManaged>& operator =(HCURSOR hCursor)
+       {
+               Attach(hCursor);
+               return *this;
+       }
+
+       void Attach(HCURSOR hCursor)
+       {
+               if(t_bManaged && m_hCursor != NULL)
+                       DestroyCursor();
+               m_hCursor = hCursor;
+       }
+
+       HCURSOR Detach()
+       {
+               HCURSOR hCursor = m_hCursor;
+               m_hCursor = NULL;
+               return hCursor;
+       }
+
+       operator HCURSOR() const { return m_hCursor; }
+
+       bool IsNull() const { return m_hCursor == NULL; }
+
+// Create/destroy methods
+       HCURSOR LoadCursor(ATL::_U_STRINGorID cursor)
+       {
+               ATLASSERT(m_hCursor == NULL);
+               m_hCursor = ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr);
+               return m_hCursor;
+       }
+
+       HCURSOR LoadSysCursor(LPCTSTR lpstrCursorName)
+       {
+               ATLASSERT(m_hCursor == NULL);
+#if (WINVER >= 0x0500)
+               ATLASSERT(lpstrCursorName == IDC_ARROW || lpstrCursorName == IDC_IBEAM || lpstrCursorName == IDC_WAIT ||
+                       lpstrCursorName == IDC_CROSS || lpstrCursorName == IDC_UPARROW || lpstrCursorName == IDC_SIZE ||
+                       lpstrCursorName == IDC_ICON || lpstrCursorName == IDC_SIZENWSE || lpstrCursorName == IDC_SIZENESW ||
+                       lpstrCursorName == IDC_SIZEWE || lpstrCursorName == IDC_SIZENS || lpstrCursorName == IDC_SIZEALL ||
+                       lpstrCursorName == IDC_NO || lpstrCursorName == IDC_APPSTARTING || lpstrCursorName == IDC_HELP ||
+                       lpstrCursorName == IDC_HAND);
+#else // !(WINVER >= 0x0500)
+               ATLASSERT(lpstrCursorName == IDC_ARROW || lpstrCursorName == IDC_IBEAM || lpstrCursorName == IDC_WAIT ||
+                       lpstrCursorName == IDC_CROSS || lpstrCursorName == IDC_UPARROW || lpstrCursorName == IDC_SIZE ||
+                       lpstrCursorName == IDC_ICON || lpstrCursorName == IDC_SIZENWSE || lpstrCursorName == IDC_SIZENESW ||
+                       lpstrCursorName == IDC_SIZEWE || lpstrCursorName == IDC_SIZENS || lpstrCursorName == IDC_SIZEALL ||
+                       lpstrCursorName == IDC_NO || lpstrCursorName == IDC_APPSTARTING || lpstrCursorName == IDC_HELP);
+#endif // !(WINVER >= 0x0500)
+               m_hCursor = ::LoadCursor(NULL, lpstrCursorName);
+               return m_hCursor;
+       }
+
+       // deprecated
+       HCURSOR LoadOEMCursor(LPCTSTR lpstrCursorName)
+       {
+               return LoadSysCursor(lpstrCursorName);
+       }
+
+       HCURSOR LoadCursor(ATL::_U_STRINGorID cursor, int cxDesired, int cyDesired, UINT fuLoad = 0)
+       {
+               ATLASSERT(m_hCursor == NULL);
+               m_hCursor = (HCURSOR) ::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad);
+               return m_hCursor;
+       }
+
+#ifndef _WIN32_WCE
+       HCURSOR LoadCursorFromFile(LPCTSTR pstrFilename)
+       {
+               ATLASSERT(m_hCursor == NULL);
+               ATLASSERT(pstrFilename != NULL);
+               m_hCursor = ::LoadCursorFromFile(pstrFilename);
+               return m_hCursor;
+       }
+#endif // !_WIN32_WCE
+
+#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
+       HCURSOR CreateCursor(int xHotSpot, int yHotSpot, int nWidth, int nHeight, CONST VOID *pvANDPlane, CONST VOID *pvXORPlane)
+       {
+               ATLASSERT(m_hCursor == NULL);
+               m_hCursor = ::CreateCursor(ModuleHelper::GetResourceInstance(), xHotSpot, yHotSpot, nWidth, nHeight, pvANDPlane, pvXORPlane);
+               return m_hCursor;
+       }
+#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
+
+#ifndef _WIN32_WCE
+       HCURSOR CreateCursorFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000)
+       {
+               ATLASSERT(m_hCursor == NULL);
+               ATLASSERT(pBits != NULL);
+               m_hCursor = (HCURSOR)::CreateIconFromResource(pBits, dwResSize, FALSE, dwVersion);
+               return m_hCursor;
+       }
+
+       HCURSOR CreateCursorFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR)
+       {
+               ATLASSERT(m_hCursor == NULL);
+               ATLASSERT(pbBits != NULL);
+               ATLASSERT(cbBits > 0);
+               m_hCursor = (HCURSOR)::CreateIconFromResourceEx(pbBits, cbBits, FALSE, dwVersion, cxDesired, cyDesired, uFlags);
+               return m_hCursor;
+       }
+#endif // !_WIN32_WCE
+
+       BOOL DestroyCursor()
+       {
+               ATLASSERT(m_hCursor != NULL);
+#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
+               BOOL bRet = ::DestroyCursor(m_hCursor);
+               if(bRet != FALSE)
+                       m_hCursor = NULL;
+               return bRet;
+#else // !(!defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))))
+               ATLTRACE2(atlTraceUI, 0, _T("Warning: This version of Windows CE does not have ::DestroyCursor()\n"));
+               return FALSE;
+#endif // !(!defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))))
+       }
+
+// Operations
+#ifndef _WIN32_WCE
+       HCURSOR CopyCursor()
+       {
+               ATLASSERT(m_hCursor != NULL);
+               return (HCURSOR)::CopyIcon((HICON)m_hCursor);
+       }
+#endif // !_WIN32_WCE
+
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+       BOOL GetCursorInfo(LPCURSORINFO pCursorInfo)
+       {
+               ATLASSERT(m_hCursor != NULL);
+               ATLASSERT(pCursorInfo != NULL);
+               return ::GetCursorInfo(pCursorInfo);
+       }
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
+};
+
+typedef CCursorT<false>   CCursorHandle;
+typedef CCursorT<true>    CCursor;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CResource - Wraps a generic Windows resource.
+//             Use it with custom resource types other than the
+//             standard RT_CURSOR, RT_BITMAP, etc.
+
+class CResource
+{
+public:
+       HGLOBAL m_hGlobal;
+       HRSRC m_hResource;
+
+// Constructor/destructor
+       CResource() : m_hGlobal(NULL), m_hResource(NULL)
+       { }
+
+       ~CResource()
+       {
+               Release();
+       }
+
+// Load methods
+       bool Load(ATL::_U_STRINGorID Type, ATL::_U_STRINGorID ID)
+       {
+               ATLASSERT(m_hResource == NULL);
+               ATLASSERT(m_hGlobal == NULL);
+
+               m_hResource = ::FindResource(ModuleHelper::GetResourceInstance(), ID.m_lpstr, Type.m_lpstr);
+               if(m_hResource == NULL)
+                       return false;
+
+               m_hGlobal = ::LoadResource(ModuleHelper::GetResourceInstance(), m_hResource);
+               if(m_hGlobal == NULL)
+               {
+                       m_hResource = NULL;
+                       return false;
+               }
+
+               return true;
+       }
+
+#ifndef _WIN32_WCE
+       bool LoadEx(ATL::_U_STRINGorID Type, ATL::_U_STRINGorID ID, WORD wLanguage)
+       {
+               ATLASSERT(m_hResource == NULL);
+               ATLASSERT(m_hGlobal == NULL);
+
+               m_hResource = ::FindResourceEx(ModuleHelper::GetResourceInstance(), ID.m_lpstr, Type.m_lpstr, wLanguage);
+               if(m_hResource == NULL)
+                       return false;
+
+               m_hGlobal = ::LoadResource(ModuleHelper::GetResourceInstance(), m_hResource);
+               if(m_hGlobal == NULL)
+               {
+                       m_hResource = NULL;
+                       return false;
+               }
+
+               return true;
+       }
+#endif // !_WIN32_WCE
+
+// Misc. operations
+       DWORD GetSize() const
+       {
+               ATLASSERT(m_hResource != NULL);
+               return ::SizeofResource(ModuleHelper::GetResourceInstance(), m_hResource);
+       }
+
+       LPVOID Lock()
+       {
+               ATLASSERT(m_hResource != NULL);
+               ATLASSERT(m_hGlobal != NULL);
+               LPVOID pVoid = ::LockResource(m_hGlobal);
+               ATLASSERT(pVoid != NULL);
+               return pVoid;
+       }
+
+       void Release()
+       {
+               if(m_hGlobal != NULL)
+               {
+                       FreeResource(m_hGlobal);
+                       m_hGlobal = NULL;
+                       m_hResource = NULL;
+               }
+       }
+};
+
+}; // namespace WTL
+
+#endif // __ATLUSER_H__
diff --git a/include/WTL/Include/atlwince.h b/include/WTL/Include/atlwince.h
new file mode 100644 (file)
index 0000000..fc6f873
--- /dev/null
@@ -0,0 +1,3001 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLWINCE_H__
+#define __ATLWINCE_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlwince.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error atlwince.h requires atlwin.h to be included first
+#endif
+
+#ifndef _WIN32_WCE
+       #error atlwince.h compiles under Windows CE only
+#elif (_WIN32_WCE < 300)
+       #error atlwince.h requires Windows CE 3.0 or higher.
+#endif
+
+#if defined(WIN32_PLATFORM_WFSP) &&  _MSC_VER < 1400 // EVC compiling SmartPhone code
+  #if (WIN32_PLATFORM_WFSP < 200)
+       #error atlwince.h requires Smartphone 2003 or higher
+  #endif
+#endif // WIN32_PLATFORM_WFSP
+
+#if defined(WIN32_PLATFORM_PSPC) &&  _MSC_VER < 1400 // EVC compiling Pocket PC code
+  #if (WIN32_PLATFORM_PSPC < 310)
+       #error atlwince.h requires Pocket PC 2002 or higher
+  #endif
+#endif // WIN32_PLATFORM_PSPC
+
+#if !defined(_AYGSHELL_H_) && !defined(__AYGSHELL_H__)
+       #error atlwince.h requires aygshell.h to be included first
+#else
+  #if defined(WIN32_PLATFORM_WFSP) && !defined(_TPCSHELL_H_)
+       #error SmartPhone dialog classes require tpcshell.h to be included first
+  #endif
+#endif
+
+#if (_MSC_VER >= 1400) // VS2005
+  #include <DeviceResolutionAware.h>
+  #define _WTL_CE_DRA
+#endif // (_MSC_VER >= 1400)
+
+#if !defined(_WTL_CE_NO_DIALOGS) &&  !defined(__ATLFRAME_H__)
+       #error Orientation aware dialog classes require atlframe.h to be included first
+#endif
+
+#if !defined(_WTL_CE_NO_APPWINDOW) &&  !defined(__ATLFRAME_H__)
+       #error Application window class require atlframe.h to be included first
+#endif
+
+#if !defined(_WTL_CE_NO_ZOOMSCROLL) &&  !defined(__ATLSCRL_H__)
+       #error ZoomScroll implementation requires atlscrl.h to be included first
+#endif
+
+#if !defined(_WTL_CE_NO_ZOOMSCROLL)
+  #if !(defined(__ATLTYPES_H__) || (defined(__ATLMISC_H__) && !defined(_WTL_NO_WTYPES)))
+       #error ZoomScroll requires _WTL_NO_WTYPES not to be defined and either atlmisc.h or atltypes.h to be included first
+  #endif // !(defined(__ATLTYPES_H__) || (defined(__ATLMISC_H__) && !defined(_WTL_NO_WTYPES)))
+#endif // !defined(_WTL_CE_NO_ZOOMSCROLL)
+
+#if !defined(WIN32_PLATFORM_WFSP) && !defined(WIN32_PLATFORM_PSPC)
+  #define _WTL_CE_NO_CONTROLS
+#endif // !defined(WIN32_PLATFORM_WFSP) && !defined(WIN32_PLATFORM_PSPC)
+
+#ifndef _WTL_CE_NO_CONTROLS
+  #ifndef __ATLCTRLS_H__
+       #error The PPC/SmartPhone controls classes require atlctrls.h to be included first
+  #endif
+
+  #include <htmlctrl.h>
+  #pragma comment(lib, "htmlview.lib")
+
+  #include <voicectl.h>
+  #pragma comment(lib, "voicectl.lib")
+
+  #ifdef WIN32_PLATFORM_PSPC
+    #include <richink.h>
+    #pragma comment(lib, "richink.lib")
+
+    #include <inkx.h>
+    #pragma comment(lib, "inkx.lib")
+
+    #include <doclist.h>
+    #pragma comment(lib, "doclist.lib")
+  #endif
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CStdDialogBase<T, t_shidiFlags, t_bModal> : Standard PPC/SmartPhone dialog base class
+// CStdDialogImplBase - Base implementation of standard dialog
+// CStdDialogImpl<T, t_shidiFlags, t_bModal> : Standard dialog implementation
+// CStdIndirectDialogImpl - implementation of standard indirect PPC/SmartPhone dialog
+// CStdAxDialogImpl<T, t_shidiFlags, t_bModal> : Standard AxDialog implementation
+// CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags> : Standard simple dialog
+// CStdDialogResizeImplBase - Base implementation of orientation resizing standard dialog
+// CStdDialogResizeImpl<T, t_shidiFlags, t_bModal> : Orientation resizing standard dialog implementation
+// CStdAxDialogResizeImpl - implementation of orientation resizing standard AxDialog
+// CStdSimpleDialogResizeImpl<T, t_wDlgTemplateID, t_shidiFlags> : Standard resizing simple dialog implementation
+// CStdOrientedDialogBase - Oriented PPC standard dialog base class
+// CStdOrientedDialogImplBase - Oriented PPC standard dialog base implementation
+// CStdOrientedDialogImpl<T, t_shidiFlags, t_bModal> : Oriented PPC standard dialog implementation
+// CStdAxOrientedDialogImpl - Oriented PPC standard AxDialog implementation
+// CStdSimpleOrientedDialog<t_wDlgTemplateID, t_wDlgLandscapeID, t_shidiFlags> : Standard simple orientable dialog
+//
+// CAppInfoBase         : Helper for application state save/restore to registry
+// CAppInfoT<T> : CAppInfoBase constructed from a CAppWindow<T>
+// CAppWindowBase<T> : Base class for PPC/SmartPhone well-behaved application window or dialog
+// CAppWindow<T> : PPC/SmartPhone well-behaved application window class
+// CAppDialog<T> : PPC/SmartPhone well-behaved application dialog class
+// CAppStdDialogImplBase - Base implementation of standard application dialogs
+// CAppStdDialogImpl<T, t_shidiFlags, t_bModal> : Implementation of standard application dialog
+// CAppStdDialogResizeImpl - implementation of orientation resizing standard application dialog
+// CAppStdAxDialogImpl - Implementation of standard application AxDialog 
+// CAppStdAxDialogResizeImpl - implementation of orientation resizing standard application AxDialog
+// CAppStdOrientedDialogImpl - implementation of oriented PPC standard application dialog
+// CAppStdAxOrientedDialogImpl - implementation of oriented PPC standard application AxDialog
+//
+// CFullScreenFrame<T, t_bHasSip> : Full screen frame class
+//
+// CZoomScrollImpl<T> : WinCE zooming implementation
+//
+// CBottomTabViewImpl<T, TBase, TWinTraits> - CBottomTabView 
+// CHtmlCtrlT<TBase> - CHtmlCtrl
+// CRichInkCtrlT<TBase> - CRichInkCtrl
+// CInkXCtrlT<TBase> - CInkXCtrl
+// CVoiceRecorderCtrlT<TBase> - CVoiceRecorderCtrl
+// CDocListCtrlT<TBase> - CDocListCtrl
+// CCapEditT<TBase> - CCapEdit
+// CTTStaticT<TBase> - CTTStatic
+// CTTButtonT<TBase> - CTTButton
+//
+// CSpinCtrlT<TBase> - CSpinCtrl : SmartPhone specific UpDown control
+// CSpinned<TBase, t_bExpandOnly> : SmartPhone association of control and Spin
+// CSpinListBox : SmartPhone spinned ListBox control
+// CExpandListBox : SmartPhone expandable ListBox control
+// CExpandEdit : SmartPhone expandable Edit control
+// CExpandCapEdit : SmartPhone expandable CapEdit control
+//
+// Global functions:
+//   AtlCreateMenuBar()
+//   AtlCreateEmptyMenuBar()
+//   AtlIsEditFocus()
+//   AtlActivateBackKey()
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// MenuBar creation functions for property sheets and dialogs
+// Frame windows use CreateSimpleCEMenuBar
+
+inline HWND AtlCreateMenuBar(SHMENUBARINFO& mbi)
+{
+       ATLASSERT(::IsWindow(mbi.hwndParent));
+       ATLVERIFY(::SHCreateMenuBar(&mbi) != FALSE);
+       return mbi.hwndMB;
+};
+
+inline HWND AtlCreateMenuBar(HWND hWnd, UINT nToolBarId = ATL_IDW_TOOLBAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0, COLORREF clrBk = 0)
+{
+       SHMENUBARINFO mbi = { sizeof(mbi), hWnd, dwFlags, nToolBarId, ModuleHelper::GetResourceInstance(), nBmpId, cBmpImages, 0, clrBk };
+       return AtlCreateMenuBar(mbi);
+}
+
+inline HWND AtlCreateEmptyMenuBar(HWND hWnd, bool bSip = true)
+{
+       SHMENUBARINFO embi = { sizeof(SHMENUBARINFO), hWnd, SHCMBF_EMPTYBAR };
+       if (!bSip)
+               embi.dwFlags |= SHCMBF_HIDESIPBUTTON;
+       
+       return AtlCreateMenuBar(embi);
+}
+       
+///////////////////////////////////////////////////////////////////////////////
+// Helper functions for SmartPhone back key handling
+
+inline bool AtlIsEditFocus()
+{
+       ATL::CWindow wCtrl = GetFocus();
+       if (wCtrl.IsWindow())
+       {
+               TCHAR szClassName[8] = {0};
+               ATLVERIFY(::GetClassName(wCtrl.m_hWnd, szClassName, 8));
+               return !_tcscmp(szClassName, _T("Edit")) || !_tcscmp(szClassName, WC_CAPEDIT);
+       }
+       return false;
+}
+
+#if defined WIN32_PLATFORM_WFSP
+inline void AtlActivateBackKey(HWND hMenuBar)
+{
+       ATLASSERT(::IsWindow(hMenuBar));
+       ::SendMessage(hMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK,
+               MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
+}
+#endif // WIN32_PLATFORM_WFSP
+
+// --- Standard PPC/SmartPhone dialogs ---
+
+#ifndef _WTL_CE_NO_DIALOGS
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdDialogBase - base class for standard PPC/SmartPhone dialogs
+
+#define WTL_STD_SHIDIF   SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN
+#define WTL_SP_SHIDIF    SHIDIF_SIZEDLGFULLSCREEN
+
+// Title setting macros
+#define WTL_DLG_TITLEHEIGHT(iHeight) static const int GetTitleHeight(){return iHeight;}
+#define WTL_DLG_NOTITLE         WTL_DLG_TITLEHEIGHT(0)
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdDialogBase - Base class for standard PPC/SmartPhone dialog
+
+template <class T, UINT t_shidiFlags, bool t_bModal = true>
+class CStdDialogBase
+{
+public:
+#ifdef WIN32_PLATFORM_PSPC
+// Pocket PC only Dialog title handling
+       const int nTitleHeight;
+
+       CStdDialogBase() : nTitleHeight(T::GetTitleHeight())
+       { }
+
+// Overloads
+       BOOL GetClientRect(LPRECT lpRect) 
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+               BOOL bRes = ::GetClientRect(pT->m_hWnd, lpRect);
+               if (nTitleHeight)
+                       lpRect->top += nTitleHeight + 1;
+               return bRes;
+       }
+
+       BOOL SetWindowText(LPCTSTR lpszString)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+               BOOL bRes = ::SetWindowText(pT->m_hWnd, lpszString);
+               if (nTitleHeight != 0)
+                       pT->DoPaintTitle();
+               return bRes;
+       }
+
+// Overrideables
+       static const int GetTitleHeight()
+       {
+       #ifdef _WTL_CE_DRA
+               return DRA::SCALEY(24);
+       #else // !_WTL_CE_DRA
+               CWindowDC dc(NULL);
+               return dc.GetDeviceCaps(LOGPIXELSY) >> 2; // LOGPIXELSY * 24 / 96,
+       #endif // !_WTL_CE_DRA
+       }
+
+       // Title painting
+       bool DoPaintTitle()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+               TCHAR sTitle[48];
+
+               // Preparation
+               CPaintDC dc(pT->m_hWnd);
+               CFont fontTitle = AtlCreateBoldFont();
+               CFontHandle fontOld = dc.SelectFont(fontTitle);
+               dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHT));
+               int nLen = pT->GetWindowText(sTitle, 48);
+               int nWidth = dc.GetDeviceCaps(HORZRES);
+
+               // Display title text
+               RECT rTitle = { 0, 0, nWidth, nTitleHeight };
+               dc.FillRect(&rTitle, COLOR_3DHIGHLIGHT);
+       #ifdef _WTL_CE_DRA
+               rTitle.left = DRA::SCALEX(8);
+       #else // !_WTL_CE_DRA
+               rTitle.left = nTitleHeight / 3; // 8 == 24 / 3
+       #endif // !_WTL_CE_DRA
+               dc.DrawText(sTitle, nLen, &rTitle, DT_VCENTER | DT_SINGLELINE);
+               dc.SelectFont(fontOld);
+
+               // Draw bottom line, 2 pixels thick if HI_RES_AWARE
+               CPenHandle penOld = dc.SelectStockPen(BLACK_PEN);
+               POINT line[4] = {{0, nTitleHeight}, {nWidth, nTitleHeight}, {0, nTitleHeight - 1}, {nWidth, nTitleHeight - 1}};
+
+       #ifdef _WTL_CE_DRA
+               int nSeg = DRA::SCALEY(1);
+       #else // !_WTL_CE_DRA
+               int nSeg = nTitleHeight / 24; 
+       #endif // !_WTL_CE_DRA
+
+               dc.Polyline(line, nSeg <= 2 ? nSeg * 2 : 4);
+               dc.SelectPen(penOld);
+
+               return false;
+       }
+
+       // Title preparation: move the dialog controls down to make room for title
+       void DialogTitleInit()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+
+               ATL::CWindow wCtl = pT->GetWindow(GW_CHILD);
+               while (wCtl.IsWindow())
+               {
+                       RECT rCtl = { 0 };
+                       wCtl.GetWindowRect(&rCtl);
+                       ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rCtl, 2);
+                       ::OffsetRect(&rCtl, 0, nTitleHeight);
+                       wCtl.MoveWindow(&rCtl, FALSE);
+                       wCtl = wCtl.GetWindow(GW_HWNDNEXT);
+               }
+       }
+
+       // SIP management
+       void DoSipInfo()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+
+               SIPINFO si = {sizeof(SIPINFO)};
+               SipGetInfo(&si);
+               if ((si.fdwFlags & SIPF_ON) ^ SIPF_ON) 
+                       si.rcVisibleDesktop.bottom = si.rcSipRect.bottom;
+               pT->MoveWindow(&si.rcVisibleDesktop, FALSE);
+       }
+
+// Title painting handler
+       LRESULT OnPaintTitle(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               return bHandled = nTitleHeight ? pT->DoPaintTitle() : FALSE;
+       }
+
+// SIP handler
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               if (wParam == SPI_SETSIPINFO)
+               {
+                       pT->DoSipInfo();
+                       return TRUE;
+               }
+               return bHandled = FALSE;
+       }
+
+#elif defined WIN32_PLATFORM_WFSP
+// SmartPhone VK_TBACK key standard management
+       LRESULT OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               const UINT uModif = (UINT)LOWORD(lParam);
+               const UINT uVirtKey = (UINT)HIWORD(lParam);
+
+               if(uVirtKey == VK_TBACK)
+                       if (AtlIsEditFocus())
+                               ::SHSendBackToFocusWindow(uMsg, wParam, lParam);
+                       else if (uModif & MOD_KEYUP)
+                                       pT->StdCloseDialog(IDCANCEL);
+               return 1;
+       }
+
+ // SmartPhone MenuBar and VK_TBACK key initialization
+       void StdSPInit()
+       {
+               T* pT = static_cast<T*>(this);
+               HWND hMenuBar = ::SHFindMenuBar(pT->m_hWnd);
+
+               if (!hMenuBar && (t_shidiFlags & SHIDIF_DONEBUTTON))
+                       hMenuBar = CreateMenuBar(ATL_IDM_MENU_DONE);
+
+               if(hMenuBar != NULL)
+                       AtlActivateBackKey(hMenuBar);
+       }
+
+       void SetStaticBold()
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+
+               CFontHandle fontBold = AtlCreateBoldFont(pT->GetFont());
+
+               ATL::CWindow wCtl = pT->GetWindow(GW_CHILD);
+
+               while (wCtl.IsWindow())
+               {
+                       if ((short int)wCtl.GetDlgCtrlID() == IDC_STATIC)
+                               wCtl.SetFont(fontBold);
+                       wCtl = wCtl.GetWindow(GW_HWNDNEXT);
+               }
+       }
+#endif // WIN32_PLATFORM_WFSP
+
+// Platform dependant initialization
+       void StdPlatformInit()
+       {
+               T* pT = static_cast<T*>(this);
+#ifdef WIN32_PLATFORM_PSPC // Pocket PC title initialization
+               if (nTitleHeight != 0)
+                       pT->DialogTitleInit();
+#elif defined(WIN32_PLATFORM_WFSP)
+               pT->StdSPInit();
+               SetStaticBold();
+#endif // WIN32_PLATFORM_WFSP
+       }
+
+       // Menu bar creation
+       HWND CreateMenuBar(UINT uiMB = T::IDD, int nBmpImages = 0)
+       {
+               T* pT = static_cast<T*>(this);
+               return AtlCreateMenuBar(pT->m_hWnd, uiMB, 0, nBmpImages ? uiMB : 0, nBmpImages);
+       }
+
+       // Dialog closing
+       void StdCloseDialog(WORD wID)
+       {
+               T* pT = static_cast<T*>(this);
+               if (t_bModal)
+                       ::EndDialog(pT->m_hWnd, wID);
+               else
+                       pT->DestroyWindow();
+       }
+
+       // Shell dialog layout initialization
+       void StdShidInit()
+       {
+               T* pT = static_cast<T*>(this);
+               SHINITDLGINFO shidi = { SHIDIM_FLAGS, pT->m_hWnd, t_shidiFlags };
+               ::SHInitDialog(&shidi);
+       }
+
+// IDC_INFOSTATIC background setting
+       LRESULT OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if (::GetDlgCtrlID((HWND)lParam) == IDC_INFOSTATIC)
+               {
+                       ::SetBkMode((HDC)wParam, TRANSPARENT);
+                       return (LRESULT)::GetSysColorBrush(COLOR_INFOBK);
+               }
+               return bHandled = FALSE;
+       }
+
+// Menu dialog ending
+       LRESULT OnMenuClose(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->StdCloseDialog((WORD)(wID - ID_MENU_OK + IDOK));
+               return 0;
+       }
+
+// Standard dialog ending: may be used with any command
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->StdCloseDialog(wID);
+               return 0;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdDialogImplBase - Base implementation of standard PPC/SmartPhone dialog
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true, class TBase = ATL::CDialogImpl< T > >
+class ATL_NO_VTABLE CStdDialogImplBase :
+               public TBase,
+               public CStdDialogBase<T, t_shidiFlags, t_bModal>
+{
+public:
+#ifdef WIN32_PLATFORM_PSPC
+       BOOL GetClientRect(LPRECT lpRect) 
+       {
+               return CStdDialogBase<T, t_shidiFlags, t_bModal>::GetClientRect(lpRect);
+       }
+
+       BOOL SetWindowText(LPCTSTR lpszString)
+       {
+               return CStdDialogBase<T, t_shidiFlags, t_bModal>::SetWindowText(lpszString);
+       }
+#endif
+
+       BEGIN_MSG_MAP(CStdDialogImplBase)
+#ifdef WIN32_PLATFORM_PSPC // Pocket PC title and SIP
+               MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key
+               MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
+#endif
+               MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
+               COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
+       END_MSG_MAP()
+       
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _DEBUG
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(t_bModal == pT->m_bModal);
+#endif
+               StdPlatformInit();
+               StdShidInit();
+               return bHandled = FALSE;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdDialogImpl - implementation of standard PPC/SmartPhone dialog
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
+class ATL_NO_VTABLE CStdDialogImpl : public CStdDialogImplBase< T, t_shidiFlags, t_bModal>
+{};
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdIndirectDialogImpl - implementation of standard indirect PPC/SmartPhone dialog
+
+#if defined __ATLDLGS_H__ 
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true>
+class ATL_NO_VTABLE CStdIndirectDialogImpl : 
+       public CIndirectDialogImpl< T, CMemDlgTemplate, CStdDialogImpl<T, t_shidiFlags, t_bModal> >
+{
+public:
+       typedef CIndirectDialogImpl< T, CMemDlgTemplate, CStdDialogImpl<T, t_shidiFlags, t_bModal> >    _baseClass;
+       typedef CStdDialogImpl<T, t_shidiFlags, t_bModal> _baseStd;
+
+       void CheckStyle()
+       {
+               // Mobile devices don't support DLGTEMPLATEEX
+               ATLASSERT(!m_Template.IsTemplateEx());
+
+               // Standard dialogs need only DS_CENTER
+               DWORD &dwStyle = m_Template.GetTemplatePtr()->style; 
+               if (dwStyle & DS_CENTER)
+                       if(t_bModal)
+                       {
+                               ATLASSERT((dwStyle & WS_CHILD) != WS_CHILD);
+                               dwStyle |= WS_POPUP;
+                       }
+                       else
+                       {
+                               if((dwStyle & WS_CHILD) != WS_CHILD)
+                                       dwStyle |= WS_POPUP;
+                       }
+       }
+
+       INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
+       {
+               ATLASSERT(t_bModal);
+
+               if (!m_Template.IsValid())
+                       CreateTemplate();
+
+               CheckStyle();
+
+               return _baseClass::DoModal(hWndParent, dwInitParam);
+       }
+
+       HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
+       {
+               ATLASSERT(!t_bModal);
+
+               if (!m_Template.IsValid())
+                       CreateTemplate();
+
+               CheckStyle();
+
+               return _baseClass::Create(hWndParent, dwInitParam);
+       }
+
+       BEGIN_MSG_MAP(CStdIndirectDialogImpl)
+               CHAIN_MSG_MAP(_baseStd)
+       END_MSG_MAP()
+
+};
+#endif // defined __ATLDLGS_H__ 
+
+#ifndef _ATL_NO_HOSTING
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdAxDialogImpl - implementation of standard  PPC/SmartPhone AxDialog
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
+class ATL_NO_VTABLE CStdAxDialogImpl : public CStdDialogImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl< T > >
+{};
+#endif // _ATL_NO_HOSTING
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdSimpleDialog - standard PPC/SmartPhone simple dialog with SHIDIF_xxx flags
+
+template <WORD t_wDlgTemplateID, UINT t_shidiFlags = WTL_STD_SHIDIF>
+class CStdSimpleDialog :
+               public ATL::CSimpleDialog<t_wDlgTemplateID, FALSE>,
+               public CStdDialogBase<CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>, t_shidiFlags>
+{
+public:
+       typedef CStdDialogBase<CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>, t_shidiFlags> baseClass;
+
+#ifdef WIN32_PLATFORM_PSPC
+       BOOL GetClientRect(LPRECT lpRect) 
+       {
+               return baseClass::GetClientRect(lpRect);
+       }
+
+       BOOL SetWindowText(LPCTSTR lpszString)
+       {
+               return baseClass::SetWindowText(lpszString);
+       }
+#endif
+
+       BEGIN_MSG_MAP(CStdSimpleDialog)
+#ifdef WIN32_PLATFORM_PSPC // Pocket PC title and SIP
+               MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key
+               MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
+#endif
+               MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
+               COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               StdPlatformInit();
+               StdShidInit();
+               return bHandled = FALSE;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdDialogResizeImplBase - Base implementation of orientation resizing standard PPC/SmartPhone dialog
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true, class TBase = ATL::CDialogImpl<T> >
+class ATL_NO_VTABLE CStdDialogResizeImplBase :
+               public CStdDialogImplBase< T, t_shidiFlags, t_bModal, TBase>,
+               public CDialogResize<T>
+{
+public:
+       // Note: BEGIN_DLGRESIZE_MAP is required in the derived class.
+
+       BEGIN_MSG_MAP(CStdResizeDialogImplBase)
+#ifdef WIN32_PLATFORM_PSPC // Pocket PC title
+               MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
+#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key
+               MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
+#endif
+               MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
+               COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
+               CHAIN_MSG_MAP(CDialogResize< T >)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifdef _DEBUG
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(t_bModal == pT->m_bModal);
+#endif
+               StdPlatformInit();
+               DlgResize_Init(FALSE);
+               StdShidInit();
+               return bHandled = FALSE;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdDialogResizeImpl - implementation of orientation resizing standard PPC/SmartPhone dialog
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
+class ATL_NO_VTABLE CStdDialogResizeImpl : public CStdDialogResizeImplBase< T, t_shidiFlags, t_bModal>
+{};
+
+#ifndef _ATL_NO_HOSTING
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdAxDialogResizeImpl - implementation of orientation resizing standard PPC/SmartPhone AxDialog
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
+class ATL_NO_VTABLE CStdAxDialogResizeImpl : public CStdDialogResizeImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl<T> >
+{};
+#endif // _ATL_NO_HOSTING
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdSimpleDialogResizeImpl - implementation of standard resizing simple dialog with SHIDIF_xxx flags
+
+// Usage:
+//     class CMyDlg : public CStdSimpleDialogResize<CMyDlg,
+//             IDD_MYDLG, SHIDIF_DONEBUTTON | SHIDIF_FULLSCREENNOMENUBAR>
+//     {
+//     public:
+//             BEGIN_DLGRESIZE_MAP(CMyDlg)
+//             ...
+//             END_DLGRESIZE_MAP()
+//     };
+
+template <class T, WORD t_wDlgTemplateID, UINT t_shidiFlags = WTL_STD_SHIDIF>
+class ATL_NO_VTABLE CStdSimpleDialogResizeImpl :
+               public CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>,
+               public CDialogResize< T >
+{
+public:
+       typedef CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>::baseClass baseClass;
+
+       BEGIN_MSG_MAP(CStdSimpleDialogResizeImpl)
+#ifdef WIN32_PLATFORM_PSPC // Pocket PC title
+               MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
+#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key
+               MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
+#endif
+               MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd)
+               COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
+               CHAIN_MSG_MAP(CDialogResize< T >)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               StdPlatformInit();
+               DlgResize_Init(FALSE);
+               StdShidInit();
+               return bHandled = FALSE;
+       }
+};
+
+#if defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC)
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdOrientedDialogBase - Oriented PPC standard dialog base class
+
+template <class T>
+class CStdOrientedDialogBase
+{
+public:
+// Operation
+       BOOL SetOrientation(DRA::DisplayMode mode)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+               ATLASSERT(mode == DRA::GetDisplayMode());
+               
+               // Derived dialog must enumerate TWO dialog templates with the same control ids and types ie:
+               // enum { IDD = IDD_MYDLG, IDD_LANDSCAPE = IDD_MYDLG_L };
+               UINT iResource = (mode == DRA::Landscape)? T::IDD_LANDSCAPE : T::IDD;
+
+               BOOL bRes = DRA::RelayoutDialog(ModuleHelper::GetResourceInstance(), pT->m_hWnd, MAKEINTRESOURCE(iResource));
+               pT->OnOrientation(mode);
+               return bRes;
+       }
+
+// Override
+       void OnOrientation(DRA::DisplayMode /*mode*/)
+       {}
+
+// Message handlers
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+               if (wParam == SETTINGCHANGE_RESET)
+               {
+                       SetOrientation(DRA::GetDisplayMode());
+                       pT->StdPlatformInit();
+                       pT->StdShidInit();
+               }
+               else if (wParam == SPI_SETSIPINFO)
+               {
+                       pT->DoSipInfo();
+                       return TRUE;
+               }
+               return bHandled = FALSE;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdOrientedDialogImplBase - Oriented PPC standard dialog base implementation
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true, class TBase = ATL::CDialogImpl<T> >
+class ATL_NO_VTABLE CStdOrientedDialogImplBase :
+               public CStdDialogImplBase< T, t_shidiFlags, t_bModal, TBase>,
+               public CStdOrientedDialogBase<T>
+{
+public:
+       BEGIN_MSG_MAP(CStdOrientedDialogImpl)
+               MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
+               MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, CStdOrientedDialogBase<T>::OnSettingChange)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
+               COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+#ifdef _DEBUG
+               ATLASSERT(t_bModal == pT->m_bModal);
+#endif
+               if (DRA::GetDisplayMode() == DRA::Landscape)
+                       SetOrientation(DRA::Landscape);
+               pT->StdPlatformInit();
+               pT->StdShidInit();
+               return bHandled = FALSE;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdOrientedDialogImpl - Oriented PPC standard dialog implementation
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
+class ATL_NO_VTABLE CStdOrientedDialogImpl : public CStdOrientedDialogImplBase< T, t_shidiFlags, t_bModal>
+{};
+
+#ifndef _ATL_NO_HOSTING
+///////////////////////////////////////////////////////////////////////////////
+// CStdAxOrientedDialogImpl - Oriented PPC standard AxDialog implementation
+
+template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
+class ATL_NO_VTABLE CStdAxOrientedDialogImpl : public CStdOrientedDialogImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl<T> >
+{};
+#endif // _ATL_NO_HOSTING
+
+///////////////////////////////////////////////////////////////////////////////
+// CStdSimpleOrientedDialog - Standard simple orientable dialog
+
+template <WORD t_wDlgTemplateID, WORD t_wDlgLandscapeID, UINT t_shidiFlags = WTL_STD_SHIDIF>
+class CStdSimpleOrientedDialog :
+               public CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>,
+               public CStdOrientedDialogBase<CStdSimpleOrientedDialog<t_wDlgTemplateID, t_wDlgLandscapeID, t_shidiFlags> >
+{
+public:
+       typedef CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>::baseClass baseClass;
+       typedef CStdOrientedDialogBase<CStdSimpleOrientedDialog<t_wDlgTemplateID, t_wDlgLandscapeID, t_shidiFlags> > baseOriented;
+
+       enum {IDD = t_wDlgTemplateID, IDD_LANDSCAPE = t_wDlgLandscapeID};
+
+       BEGIN_MSG_MAP(CStdSimpleDialog)
+               MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
+               MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, baseOriented::OnSettingChange)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd)
+               COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
+       END_MSG_MAP()
+
+               LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if (DRA::GetDisplayMode() == DRA::Landscape)
+                       SetOrientation(DRA::Landscape);
+               StdPlatformInit();
+               StdShidInit();
+               return bHandled = FALSE;
+       }
+};
+
+#endif // _WTL_CE_DRA
+
+
+#endif // _WTL_CE_NO_DIALOGS
+
+
+// --- PPC/SmartPhone application window and helpers ---
+
+#ifndef _WTL_CE_NO_APPWINDOW
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppInfoBase - Helper for application state save/restore to registry
+
+class CAppInfoBase
+{
+public:
+       ATL::CRegKey m_Key;
+
+       CAppInfoBase(ATL::_U_STRINGorID sAppKey)
+       {
+               m_Key.Create(HKEY_CURRENT_USER, sAppKey.m_lpstr);
+               ATLASSERT(m_Key.m_hKey);
+       }
+
+       template <class V>
+       LONG Save(V& val, ATL::_U_STRINGorID sName)
+       {
+               return ::RegSetValueEx(m_Key, sName.m_lpstr, 0, REG_BINARY, (LPBYTE)&val, sizeof(V));
+       }
+
+       template <class V>
+       LONG Save(int nb, V& val0, ATL::_U_STRINGorID sName)
+       {
+               return ::RegSetValueEx(m_Key, sName.m_lpstr, 0, REG_BINARY, (LPBYTE)&val0, nb * sizeof(V));
+       }
+
+       template <class V>
+       LONG Restore(V& val, ATL::_U_STRINGorID sName)
+       {
+               DWORD valtype;
+               DWORD bufSize = sizeof(V);
+               return ::RegQueryValueEx(m_Key, sName.m_lpstr, 0, &valtype, (LPBYTE)&val, &bufSize);
+       }
+
+       template <class V>
+       LONG Restore(int nb, V& val0, ATL::_U_STRINGorID sName)
+       {
+               DWORD valtype;
+               DWORD bufSize = nb * sizeof(V);
+               return ::RegQueryValueEx(m_Key, sName.m_lpstr, 0, &valtype, (LPBYTE)&val0, &bufSize);
+       }
+
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+#if (_ATL_VER < 0x0800)
+       LONG Save(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName)
+       {
+               return m_Key.SetValue(sval, sName.m_lpstr);
+       }
+
+       LONG Restore(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName)
+       {
+               DWORD size = MAX_PATH;
+               LONG res = m_Key.QueryValue(sval.GetBuffer(size), sName.m_lpstr, &size);
+               sval.ReleaseBuffer();
+               return res;
+       }
+#else // !(_ATL_VER < 0x0800)
+       LONG Save(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName)
+       {
+               return m_Key.SetStringValue(sName.m_lpstr, sval);
+       }
+
+       LONG Restore(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName)
+       {
+               DWORD size = MAX_PATH;
+               LONG res = m_Key.QueryStringValue(sName.m_lpstr, sval.GetBuffer(size), &size);
+               sval.ReleaseBuffer();
+               return res;
+       }
+#endif // !(_ATL_VER < 0x0800)
+#else
+  #pragma message("Warning: CAppInfoBase compiles without CString support. Do not use CString in Save or Restore.")
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
+       
+#if (_ATL_VER < 0x0800)
+       LONG Save(LPCTSTR sval, ATL::_U_STRINGorID sName)
+       {
+               return m_Key.SetValue(sval, sName.m_lpstr);
+       }
+
+       LONG Restore(LPTSTR sval, ATL::_U_STRINGorID sName, DWORD *plength)
+       {
+               return m_Key.QueryValue(sval, sName.m_lpstr, plength);
+       }
+#else // !(_ATL_VER < 0x0800)
+       LONG Save(LPCTSTR sval, ATL::_U_STRINGorID sName)
+       {
+               return m_Key.SetStringValue(sName.m_lpstr, sval);
+       }
+
+       LONG Restore(LPTSTR sval, ATL::_U_STRINGorID sName, DWORD *plength)
+       {
+               return m_Key.QueryStringValue(sName.m_lpstr, sval, plength);
+       }
+#endif // !(_ATL_VER < 0x0800)
+       
+       LONG Delete(ATL::_U_STRINGorID sName)
+       {
+               return  m_Key.DeleteValue(sName.m_lpstr);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppInfoT - CAppInfoBase constructed from a class with T::GetAppKey() 
+
+// Macro for declaring AppKey
+#define DECLARE_APPKEY(uAppKey) \
+       static LPCTSTR GetAppKey() \
+       { \
+               static LPCTSTR sAppKey = ATL::_U_STRINGorID(uAppKey).m_lpstr; \
+               return sAppKey; \
+       }
+
+template <class T>
+class CAppInfoT : public CAppInfoBase
+{
+public:
+       CAppInfoT() : CAppInfoBase(T::GetAppKey()){}
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppWindowBase - Base class for PPC/SmartPhone "well-behaved" application window or dialog
+
+// Macros for declaring frame WNDCLASS and AppKey
+#define DECLARE_APP_FRAME_CLASS(WndClassName, uCommonResourceID, uAppKey) \
+       DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
+       DECLARE_APPKEY(uAppKey)
+
+#define DECLARE_APP_FRAME_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd, uAppKey) \
+       DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
+       DECLARE_APPKEY(uAppKey)
+
+template <class T>
+class CAppWindowBase
+{
+public:
+       typedef class CAppInfoT< T > CAppInfo;
+
+#ifndef WIN32_PLATFORM_WFSP
+       SHACTIVATEINFO m_sai; // NoOp on SmartPhones
+#endif // WIN32_PLATFORM_WFSP
+
+       bool m_bHibernate;
+
+       CAppWindowBase< T >() : m_bHibernate(false)
+       {
+#ifndef WIN32_PLATFORM_WFSP
+               SHACTIVATEINFO sai = { sizeof(SHACTIVATEINFO) };
+               m_sai = sai;
+#endif // WIN32_PLATFORM_WFSP
+       };
+
+       // Same as WTL 7.1 AppWizard generated ActivatePreviousInstance + SendMessage WM_COPYDATA
+       static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR  lpstrCmdLine, bool bDialog)
+       {
+               // requires T does DECLARE_APP_FRAME_CLASS, DECLARE_APP_FRAME_CLASS_EX or DECLARE_APP_DLG_CLASS
+               CFrameWndClassInfo& classInfo = T::GetWndClassInfo();
+
+               ATLVERIFY(::LoadString(hInstance, classInfo.m_uCommonResourceID, classInfo.m_szAutoName, sizeof(classInfo.m_szAutoName)/sizeof(classInfo.m_szAutoName[0])) != 0);
+
+               classInfo.m_wc.lpszClassName = classInfo.m_szAutoName;
+
+               const TCHAR* pszClass = classInfo.m_wc.lpszClassName;
+
+               if(NULL == pszClass || '\0' == *pszClass)
+               {
+                       return E_FAIL;
+               }
+
+               const DWORD dRetryInterval = 100;
+               const int iMaxRetries = 25;
+
+               for(int i = 0; i < iMaxRetries; ++i)
+               {
+                       HANDLE hMutex = CreateMutex(NULL, FALSE, pszClass);
+
+                       DWORD dw = GetLastError();
+
+                       if(NULL == hMutex)
+                       {
+                               HRESULT hr;
+
+                               switch(dw)
+                               {
+                               case ERROR_INVALID_HANDLE:
+                                       // A non-mutext object with this name already exists.
+                                       hr = E_INVALIDARG;
+                                       break;
+                               default:
+                                       // This should never happen...
+                                       hr = E_FAIL;
+                               }
+
+                               return hr;
+                       }
+
+                       // If the mutex already exists, then there should be another instance running
+                       if(dw == ERROR_ALREADY_EXISTS)
+                       {
+                               CloseHandle(hMutex);
+                               
+                               HWND hwnd = NULL;
+                               if (bDialog)
+                                       hwnd = FindWindow(NULL, pszClass);
+                               else
+                                       hwnd = FindWindow(pszClass, NULL);
+
+                               if(hwnd == NULL)
+                               {
+                                       Sleep(dRetryInterval);
+                                       continue;
+                               }
+                               else
+                               {
+                                       // Transmit our params to previous instance
+                                       if (lpstrCmdLine && *lpstrCmdLine)
+                                       {
+                                               COPYDATASTRUCT cd = { NULL, sizeof(TCHAR) * (wcslen(lpstrCmdLine) + 1), (PVOID)lpstrCmdLine };
+                                               ::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cd);
+                                       }
+                                       // Set the previous instance as the foreground window
+                                       if(0 != SetForegroundWindow(reinterpret_cast<HWND>(reinterpret_cast<ULONG>(hwnd) | 0x1)))
+                                               return S_FALSE;
+                               }
+                       }
+                       else
+                       {
+                               return S_OK;
+                       }
+               }
+               return S_OK;
+       }
+
+// Operations overriden in derived class
+       bool AppHibernate(bool /*bHibernate*/)
+       {
+               return false;
+       }
+
+       bool AppNewInstance(LPCTSTR /*lpstrCmdLine*/)
+       {
+               return false;
+       }
+
+       void AppSave()
+       {
+       }
+
+#ifdef WIN32_PLATFORM_WFSP 
+       void AppBackKey() 
+       {
+               ::SHNavigateBack();
+       }
+#endif
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CAppWindowBase)
+               MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
+#ifdef WIN32_PLATFORM_WFSP
+               MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
+#else
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+#endif // WIN32_PLATFORM_WFSP
+               MESSAGE_HANDLER(WM_HIBERNATE, OnHibernate)
+               MESSAGE_HANDLER(WM_COPYDATA, OnNewInstance)
+               MESSAGE_HANDLER(WM_CLOSE, OnClose)
+       END_MSG_MAP()
+
+       LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               if (m_bHibernate)
+                       m_bHibernate = pT->AppHibernate(false);
+#ifndef WIN32_PLATFORM_WFSP
+               ::SHHandleWMActivate(pT->m_hWnd, wParam, lParam, &m_sai, 0);
+#else
+               wParam;
+               lParam;
+#endif // WIN32_PLATFORM_WFSP
+                return bHandled = FALSE;
+       }
+
+#ifdef WIN32_PLATFORM_WFSP
+// SmartPhone VK_TBACK key standard management
+       LRESULT OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               const UINT uModif = (UINT)LOWORD(lParam);
+               const UINT uVirtKey = (UINT)HIWORD(lParam);
+               if(uVirtKey == VK_TBACK)
+                       if (AtlIsEditFocus())
+                               ::SHSendBackToFocusWindow(uMsg, wParam, lParam);
+                       else if (uModif & MOD_KEYUP)
+                               pT->AppBackKey();
+               return 1;
+       }
+
+#else // !WIN32_PLATFORM_WFSP
+// PPC SIP handling
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               bHandled = FALSE;
+               return ::SHHandleWMSettingChange(pT->m_hWnd, wParam, lParam, &m_sai);
+       }
+#endif // !WIN32_PLATFORM_WFSP
+
+       LRESULT OnHibernate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               return m_bHibernate = pT->AppHibernate(true);
+       }
+
+       LRESULT OnNewInstance(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam;
+               return pT->AppNewInstance((LPCTSTR)pcds->lpData);
+       }
+
+       LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->AppSave();
+               bHandled = FALSE;
+               return 1;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppWindow - PPC/SmartPhone "well-behaved" application window class
+
+template <class T>
+class CAppWindow : public CAppWindowBase< T >
+{
+public:
+       // Same as WTL 7.1 AppWizard generated Run + lpstrCmdLine in CreateEx
+       static int AppRun(LPTSTR lpstrCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL)
+       {
+               CMessageLoop theLoop;
+               _Module.AddMessageLoop(&theLoop);
+
+               T wndMain;
+
+               if(wndMain.CreateEx(NULL, NULL, 0, 0, lpstrCmdLine) == NULL)
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("Main window creation failed!\n"));
+                       return 0;
+               }
+
+               wndMain.ShowWindow(nCmdShow);
+
+               int nRet = theLoop.Run();
+
+               _Module.RemoveMessageLoop();
+               return nRet;
+       }
+
+       static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR  lpstrCmdLine)
+       {
+               return CAppWindowBase< T >::ActivatePreviousInstance(hInstance, lpstrCmdLine, false);
+       }
+};
+
+
+#ifndef _WTL_CE_NO_DIALOGS
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppDialog - PPC/SmartPhone "well-behaved" dialog application class
+
+// Macro for declaring dialog WNDCLASS and AppKey
+#define DECLARE_APP_DLG_CLASS(WndClassName, uCommonResourceID, uAppKey) \
+       static WTL::CFrameWndClassInfo& GetWndClassInfo() \
+       { \
+               static WTL::CFrameWndClassInfo wc = \
+               { \
+                       { 0, (WNDPROC)StartDialogProc, \
+                       0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
+                       NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
+               }; \
+               return wc; \
+       }; \
+       DECLARE_APPKEY(uAppKey)
+
+template <class T>
+class CAppDialog : public CAppWindowBase< T >
+{
+public:
+       static int AppRun(LPTSTR lpstrCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL)
+       {
+               CMessageLoop theLoop;
+               _Module.AddMessageLoop(&theLoop);
+
+               T dlgMain;
+
+               if(dlgMain.Create(NULL, (LPARAM)lpstrCmdLine) == NULL)
+               {
+                       ATLTRACE2(atlTraceUI, 0, _T("Main dialog creation failed!\n"));
+                       return 0;
+               }
+
+               dlgMain.ShowWindow(nCmdShow);
+
+               int nRet = theLoop.Run();
+
+               _Module.RemoveMessageLoop();
+               return nRet;
+       }
+
+       static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR  lpstrCmdLine)
+       {
+               return CAppWindowBase< T >::ActivatePreviousInstance(hInstance, lpstrCmdLine, true);
+       };
+};
+
+// PPC/SmartPhone standard application dialogs
+
+#ifdef WIN32_PLATFORM_WFSP
+#define WTL_APP_SHIDIF WTL_SP_SHIDIF
+#else
+#define WTL_APP_SHIDIF WTL_STD_SHIDIF
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppStdDialogImplBase - Base implementation of standard application dialogs
+
+template <class T, class TImplBase, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
+class ATL_NO_VTABLE CAppStdDialogImplBase :
+               public TImplBase, 
+               public CAppDialog< T >
+{ 
+public:
+       WTL_DLG_NOTITLE;
+
+       void StdCloseDialog(int nVal)
+       {
+               T* pT = static_cast<T*>(this);
+               if (nVal != IDCANCEL)
+                       pT->AppSave();
+               if (t_bModal == false)
+               {
+                       pT->DestroyWindow();
+                       ::PostQuitMessage(nVal);
+               }
+               else
+                       ::EndDialog(pT->m_hWnd, nVal);
+       }
+       
+       BEGIN_MSG_MAP(CAppStdDialogImplBase)
+               MESSAGE_HANDLER(WM_CLOSE, OnSystemClose)
+               CHAIN_MSG_MAP(TImplBase)
+               CHAIN_MSG_MAP(CAppDialog< T >)
+       END_MSG_MAP()
+
+       LRESULT OnSystemClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               pT->StdCloseDialog(IDCANCEL);
+               return 0;
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppStdDialogImpl - Implementation of standard application dialog 
+
+template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
+class ATL_NO_VTABLE CAppStdDialogImpl :
+               public CAppStdDialogImplBase<T, CStdDialogImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
+{};
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppStdDialogResizeImpl - implementation of orientation resizing standard application dialog
+
+template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
+class ATL_NO_VTABLE CAppStdDialogResizeImpl :
+               public CAppStdDialogImplBase<T, CStdDialogResizeImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
+{};
+
+#ifndef _ATL_NO_HOSTING
+///////////////////////////////////////////////////////////////////////////////
+// CAppStdAxDialogImpl - Implementation of standard application AxDialog 
+
+template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
+class ATL_NO_VTABLE CAppStdAxDialogImpl :
+               public CAppStdDialogImplBase<T, CStdAxDialogImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
+{};
+
+///////////////////////////////////////////////////////////////////////////////
+// CAppStdAxDialogResizeImpl - implementation of orientation resizing standard application AxDialog
+
+template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
+class ATL_NO_VTABLE CAppStdAxDialogResizeImpl :
+               public CAppStdDialogImplBase<T, CStdAxDialogResizeImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
+{};
+#endif // _ATL_NO_HOSTING
+
+#if defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC)
+///////////////////////////////////////////////////////////////////////////////
+// CAppStdOrientedDialogImpl - implementation of oriented PPC standard application dialog
+
+template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
+class ATL_NO_VTABLE CAppStdOrientedDialogImpl :
+               public CAppStdDialogImplBase<T, CStdOrientedDialogImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
+{};
+
+#ifndef _ATL_NO_HOSTING
+///////////////////////////////////////////////////////////////////////////////
+// CAppStdAxOrientedDialogImpl - implementation of oriented PPC standard application AxDialog
+
+template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
+class ATL_NO_VTABLE CAppStdAxOrientedDialogImpl :
+               public CAppStdDialogImplBase<T, CStdAxOrientedDialogImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
+{};
+#endif // _ATL_NO_HOSTING
+
+#endif // defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC)
+
+#endif // _WTL_CE_NO_DIALOGS
+
+#endif // _WTL_CE_NO_APPWINDOW
+
+
+// --- Full screen support ---
+
+#ifndef _WTL_CE_NO_FULLSCREEN
+
+///////////////////////////////////////////////////////////////////////////////
+// CFullScreenFrame - full screen frame implementation
+
+template <class T, bool t_bHasSip = true>
+class CFullScreenFrame
+{
+public:
+       bool m_bFullScreen;
+
+       CFullScreenFrame() : m_bFullScreen(false)
+       { }
+
+// Operation   
+       void SetFullScreen(bool bFull)
+       {
+               m_bFullScreen = bFull;
+               ShowTaskBar(!bFull, false);
+               ShowMenuBar(!bFull);
+       }
+
+// Manage TaskBar for modal dialogs and property sheets
+       template <class D>
+       int FSDoModal(D& dlg)
+       {
+               T* pT = static_cast<T*>(this);
+               pT;   // avoid level 4 warning
+               ATLASSERT(pT->IsWindow());
+               if (m_bFullScreen)   // Show taskbar if hidden
+                       ShowTaskBar(true, false);
+               int iRet = dlg.DoModal();
+               if (m_bFullScreen)   // Hide taskbar if restored
+                       ShowTaskBar(false);
+               return iRet;
+       }
+
+// Implementation
+       void ShowMenuBar(bool bShow)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+               ATL::CWindow MenuBar = pT->m_hWndCECommandBar;
+               ATLASSERT(MenuBar.IsWindow());
+               MenuBar.ShowWindow(bShow ? SW_SHOWNORMAL : SW_HIDE);
+               pT->SizeToMenuBar();
+       }
+       
+       void ShowTaskBar(bool bShow, bool bRepaint = true)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(pT->IsWindow());
+               RECT rect = { 0 };
+               SystemParametersInfo(SPI_GETWORKAREA, NULL, &rect, FALSE);
+               if (!bShow)
+                       rect.top = 0;
+
+#ifdef WIN32_PLATFORM_PSPC // Pocket PC code
+               UINT uShow = t_bHasSip ? SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON : SHFS_SHOWTASKBAR | SHFS_HIDESIPBUTTON;         
+               SHFullScreen(pT->m_hWnd, bShow ? uShow : SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON);
+#elif _WIN32_WCE > 0x500 // Smartphone 2005 code
+               SHFullScreen(pT->m_hWnd, bShow ? SHFS_SHOWTASKBAR : SHFS_HIDETASKBAR);
+#else // Smartphone 2003
+               HWND hTaskBar = FindWindow(_T("tray"), NULL);
+               ATLASSERT(::IsWindow(hTaskBar));
+               ::ShowWindow(hTaskBar, bShow ? SW_SHOW : SW_HIDE);
+#endif // WIN32_PLATFORM_PSPC
+
+               pT->MoveWindow(&rect, bRepaint);
+       }
+
+// Message map and handler
+       BEGIN_MSG_MAP(CFullScreenFrame)
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+               MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
+       END_MSG_MAP()
+
+       LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+#ifndef SETTINGCHANGE_RESET // not defined for PPC 2002
+       #define SETTINGCHANGE_RESET SPI_SETWORKAREA
+#endif
+               if (m_bFullScreen && (wParam == SETTINGCHANGE_RESET))
+                       SetFullScreen(m_bFullScreen);
+               return bHandled = FALSE;
+       }
+
+       LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if (m_bFullScreen)
+               {
+                       ShowTaskBar(!wParam);
+                       ShowMenuBar(!wParam);
+               }
+               return bHandled = FALSE;
+       }
+};
+
+#endif // _WTL_CE_NO_FULLSCREEN
+
+
+// --- WinCE zoom support ---
+
+#ifndef _WTL_CE_NO_ZOOMSCROLL
+
+///////////////////////////////////////////////////////////////////////////////
+// CZoomScrollImpl - WinCE zooming implementation on top of CScrollImpl
+
+template <class T>
+class  CZoomScrollImpl: public CScrollImpl< T >
+{
+public:
+// Data members
+       _WTYPES_NS::CSize m_sizeTrue;
+       double  m_fzoom;
+
+// Creation
+       CZoomScrollImpl() : m_sizeTrue(0), m_fzoom(1.)
+       { }
+
+// Zoom operations and access
+       void SetZoomScrollSize(_WTYPES_NS::CSize sizeTrue, double fzoom = 1., BOOL bRedraw = TRUE)
+       {
+               ATLASSERT(fzoom > 0.);
+               m_sizeTrue = sizeTrue;
+               m_fzoom = fzoom;
+
+               CScrollImpl< T >::SetScrollSize(sizeTrue / fzoom, bRedraw);
+       }
+
+       void SetZoomScrollSize(int cx, int cy, double fzoom=1., BOOL bRedraw = TRUE)
+       {
+               SetZoomScrollSize(_WTYPES_NS::CSize(cx, cy), fzoom, bRedraw);
+       }
+
+       void SetZoom(double fzoom, BOOL bRedraw = TRUE)
+       {
+               _WTYPES_NS::CPoint ptCenter = WndtoTrue(m_sizeClient / 2);
+               _WTYPES_NS::CSize sizePage = GetScrollPage();
+               _WTYPES_NS::CSize sizeLine = GetScrollLine();
+
+               SetZoomScrollSize(GetScrollSize(), fzoom, bRedraw);
+
+               SetScrollLine(sizeLine);
+               SetScrollPage(sizePage);
+               _WTYPES_NS::CPoint ptOffset = ptCenter - (m_sizeClient / 2) * fzoom;
+               SetScrollOffset(ptOffset, bRedraw);
+       }
+
+       double GetZoom()
+       {
+               return m_fzoom;
+       }
+
+// CScrollImpl overrides
+       void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
+       {
+               CScrollImpl< T >::SetScrollOffset((int)(x / m_fzoom), (int)(y / m_fzoom), bRedraw);
+       }
+
+       void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
+       {
+               SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
+       }
+
+       void GetScrollOffset(POINT& ptOffset)
+       {
+               ptOffset.x = (LONG)(m_ptOffset.x * m_fzoom);
+               ptOffset.y = (LONG)(m_ptOffset.y * m_fzoom);
+       }
+
+       void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE)
+       {
+               SetZoomScrollSize(cx, cy, GetZoom(), bRedraw);
+       }
+
+       void SetScrollSize(SIZE sizeTrue, BOOL bRedraw = TRUE)
+       {
+               SetZoomScrollSize(sizeTrue, GetZoom(), bRedraw);
+       }
+
+       void GetScrollSize(SIZE& sizeTrue) const
+       {
+               sizeTrue = m_sizeTrue;
+       }
+
+       void SetScrollPage(int cxPage, int cyPage)
+       {
+               SetScrollPage(_WTYPES_NS::CSize(cxPage, cyPage));
+       }
+
+       void SetScrollPage(SIZE sizePage)
+       {
+               CScrollImpl< T >::SetScrollPage(sizePage / m_fzoom);
+       }
+
+       void GetScrollPage(SIZE& sizePage) const
+       {
+               sizePage = m_sizePage * m_fzoom;
+       }
+
+       void SetScrollLine(int cxLine, int cyLine)
+       {
+               SetScrollLine(_WTYPES_NS::CSize(cxLine, cyLine));
+       }
+
+       void SetScrollLine(SIZE sizeLine)
+       {
+               CScrollImpl< T >::SetScrollLine(sizeLine / m_fzoom);
+       }
+
+       void GetScrollLine(SIZE& sizeLine) const
+       {
+               sizeLine = m_sizeLine * m_fzoom;
+       }
+
+// Data access complements
+       _WTYPES_NS::CSize GetScrollSize()
+       {
+               return m_sizeTrue;
+       }
+
+       _WTYPES_NS::CSize GetScrollPage()
+       {
+               return m_sizePage * m_fzoom;
+       }
+
+       _WTYPES_NS::CSize GetScrollLine()
+       {
+               return m_sizeLine * m_fzoom;
+       }
+
+       _WTYPES_NS::CPoint GetScrollOffset()
+       {
+               return (_WTYPES_NS::CSize)m_ptOffset * m_fzoom;
+       }
+
+// Helper coordinate functions
+       _WTYPES_NS::CPoint WndtoTrue(CPoint ptW)
+       {
+               return (_WTYPES_NS::CSize)ptW * GetZoom() + GetScrollOffset();
+       }
+
+       void WndtoTrue(LPPOINT aptW, int nPts)   // in place coord transformation
+       {
+               for (int i = 0 ; i < nPts ; i++)
+                       aptW[i] = WndtoTrue(aptW[i]);
+       }
+
+       void WndtoTrue(LPRECT prectW)   // in place coord transformation
+       {
+               WndtoTrue((LPPOINT)prectW, 2);
+       }
+
+       _WTYPES_NS::CPoint TruetoWnd(CPoint ptT)
+       {
+               return (ptT - GetScrollOffset()) / GetZoom();
+       }
+
+       void TruetoWnd(LPPOINT aptT, int nPts)   // in place coord transformation
+       {
+               for (int i = 0 ; i < nPts ; i++)
+                       aptT[i] = TruetoWnd(aptT[i]);
+       }
+
+       void TruetoWnd(LPRECT prectT)   // in place coord transformation
+       {
+               TruetoWnd((LPPOINT)prectT, 2);
+       }
+
+// Drawing operations : assume adequate setting of data members
+       BOOL Draw(HBITMAP hbm, HDC hdestDC, DWORD dwROP = SRCCOPY)
+       {
+               CDC memDC = CreateCompatibleDC(hdestDC);
+               CBitmapHandle bmpOld = memDC.SelectBitmap(hbm);
+               BOOL bRes = Draw(memDC, hdestDC, dwROP);
+               memDC.SelectBitmap(bmpOld);
+               return bRes;
+       }
+
+       BOOL Draw(HDC hsourceDC, HDC hdestDC, DWORD dwROP = SRCCOPY)
+       {
+               CDCHandle destDC = hdestDC;
+               destDC.SetViewportOrg(0,0);
+               _WTYPES_NS::CPoint ptOffset = GetScrollOffset();
+               _WTYPES_NS::CSize sizeZClient = m_sizeClient * GetZoom();
+               return destDC.StretchBlt(0, 0, m_sizeClient.cx, m_sizeClient.cy, hsourceDC, ptOffset.x, ptOffset.y, sizeZClient.cx, sizeZClient.cy, dwROP);
+       }
+
+#ifdef _IMAGING_H
+       BOOL Draw(IImage* pIImage, HDC hdestDC)
+       {
+               CDCHandle destDC = hdestDC;
+               destDC.SetViewportOrg(0,0);
+               return SUCCEEDED(pIImage->Draw(destDC, _WTYPES_NS::CRect(-_WTYPES_NS::CPoint(m_ptOffset), m_sizeAll), NULL));
+       }
+#endif
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CZoomScrollImpl< T >)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
+               CHAIN_MSG_MAP(CScrollImpl< T >)
+       END_MSG_MAP()
+       
+       LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               T* pT = static_cast<T*>(this);
+               ATLASSERT(::IsWindow(pT->m_hWnd));
+               if ((GetScrollExtendedStyle() & SCRL_ERASEBACKGROUND))
+               {
+                       _WTYPES_NS::CRect rect;
+                       pT->GetClientRect(rect);
+                       _WTYPES_NS::CSize sizeClient=rect.Size();
+
+                       if (m_sizeAll.cx < sizeClient.cx || m_sizeAll.cy < sizeClient.cy)
+                       {
+                               CDCHandle hdc = (HDC)wParam;
+                               HBRUSH hbr = GetSysColorBrush((int)T::GetWndClassInfo().m_wc.hbrBackground - 1);
+
+                               if (m_sizeAll.cx < sizeClient.cx)
+                               {
+                                       _WTYPES_NS::CRect rectBG(_WTYPES_NS::CPoint(m_sizeAll.cx, 0), sizeClient);
+                                       hdc.FillRect(rectBG, hbr);
+                               }
+
+                               if (m_sizeAll.cy < sizeClient.cy)
+                               {
+                                       _WTYPES_NS::CRect rectBG(_WTYPES_NS::CPoint(0, m_sizeAll.cy), sizeClient);
+                                       hdc.FillRect(rectBG, hbr);
+                               }
+                       }
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+
+               return 1;
+       }
+};
+
+#endif // _WTL_CE_NO_ZOOMSCROLL
+
+#ifndef _WTL_CE_NO_CONTROLS
+
+// --- PPC bottom TabView control ---
+
+#if defined(__ATLCTRLX_H__) && defined(WIN32_PLATFORM_PSPC)
+
+///////////////////////////////////////////////////////////////////////////////
+// CBottomTabViewImpl
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
+class ATL_NO_VTABLE CBottomTabViewImpl : public CTabViewImpl<T, TBase, TWinTraits>
+{
+public:
+       DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE)
+
+// Implementation overrideables
+       bool CreateTabControl()
+       {
+               m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | TCS_BOTTOM, 0, m_nTabID);
+
+               ATLASSERT(m_tab.m_hWnd != NULL);
+               if(m_tab.m_hWnd == NULL)
+                       return false;
+
+               m_tab.SendMessage(CCM_SETVERSION, COMCTL32_VERSION);
+               m_tab.SetItemExtra(sizeof(TABVIEWPAGE));
+
+               T* pT = static_cast<T*>(this);
+               m_cyTabHeight = pT->CalcTabHeight();
+
+               return true;
+       }
+
+       int CalcTabHeight()
+       {
+               int nCount = m_tab.GetItemCount();
+               TCITEMEXTRA tcix = { 0 };
+               tcix.tciheader.mask = TCIF_TEXT;
+               tcix.tciheader.pszText = _T("NS");
+               int nIndex = m_tab.InsertItem(nCount, tcix);
+
+               RECT rect = { 0 };
+               SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
+               RECT rcWnd = rect;
+
+               m_tab.AdjustRect(FALSE, &rect);
+               rcWnd.top = rect.bottom;
+               ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle());
+               m_tab.DeleteItem(nIndex);
+
+               return rcWnd.bottom - rcWnd.top;
+       }
+
+       void UpdateLayout()
+       {
+               RECT rect;
+               GetClientRect(&rect);
+
+               if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0))
+                       m_tab.SetWindowPos(NULL, 0, rect.bottom - m_cyTabHeight, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER /*| SWP_SHOWWINDOW*/);
+
+               if(m_nActivePage != -1)
+                               ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, 0, rect.right - rect.left, rect.bottom - m_cyTabHeight, SWP_NOZORDER);
+       }
+
+};
+
+class CBottomTabView : public CBottomTabViewImpl<CBottomTabView>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("WTL_BottomTabView"), 0, COLOR_APPWORKSPACE)
+};
+
+#endif // defined(__ATLCTRLX_H__) && defined(WIN32_PLATFORM_PSPC)
+
+
+// --- PPC/SmartPhone controls ---
+
+////////////////////////////////////////////////////////////////////////////////
+// These are wrapper classes for the Pocket PC 2002/2003 and SmartPhone 2003 controls
+// To implement a window based on a control, use following:
+// Example: Implementing a window based on a Html control
+//
+// class CMyHtml : CWindowImpl<CMyHtml, CHtmlCtrl>
+// {
+// public:
+//      BEGIN_MSG_MAP(CMyHtml)
+//          // put your message handler entries here
+//      END_MSG_MAP()
+// };
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// CHtmlCtrl
+
+template <class TBase>
+class CHtmlCtrlT : public TBase
+{
+public:
+// Constructors
+       CHtmlCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CHtmlCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+               ATLASSERT(hWnd != NULL);   // Did you remember to call InitHTMLControl(hInstance) ??
+               return hWnd;
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_HTML;
+       }
+
+#if (_WIN32_WCE >= 400)
+       void AddStyle(LPCWSTR pszStyle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ADDSTYLE, 0, (LPARAM)pszStyle);
+       }
+#endif // (_WIN32_WCE >= 400)
+
+       void AddText(BOOL bPlainText, LPCSTR pszText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ADDTEXT, (WPARAM)bPlainText, (LPARAM)pszText);
+       }
+
+       void AddHTML(LPCSTR pszHTML)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ADDTEXT, (WPARAM)FALSE, (LPARAM)pszHTML);
+       }
+
+       void AddText(BOOL bPlainText, LPCWSTR pszText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ADDTEXTW, (WPARAM)bPlainText, (LPARAM)pszText);
+       }
+
+       void AddHTML(LPCWSTR pszHTML)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ADDTEXTW, (WPARAM)FALSE, (LPARAM)pszHTML);
+       }
+
+       void Anchor(LPCSTR pszAnchor)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ANCHOR, 0, (LPARAM)pszAnchor);
+       }
+
+       void Anchor(LPCWSTR pszAnchor)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ANCHORW, 0, (LPARAM)pszAnchor);
+       }
+
+#if (_WIN32_WCE >= 420)
+       void GetBrowserDispatch(IDispatch** ppDispatch)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(ppDispatch);
+               ATLASSERT(*ppDispatch==NULL);
+               ::SendMessage(m_hWnd, DTM_BROWSERDISPATCH, 0, (LPARAM)ppDispatch);
+       }
+       void GetDocumentDispatch(IDispatch** ppDispatch)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(ppDispatch);
+               ATLASSERT(*ppDispatch==NULL);
+               ::SendMessage(m_hWnd, DTM_DOCUMENTDISPATCH , 0, (LPARAM)ppDispatch);
+       }
+#endif // (_WIN32_WCE >= 420)
+
+       void Clear()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_CLEAR, 0, 0L);
+       }
+
+       void EnableClearType(BOOL bEnable = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ENABLECLEARTYPE, 0, (LPARAM)bEnable);
+       }
+
+       void EnableContextMenu(BOOL bEnable = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ENABLECONTEXTMENU, 0, (LPARAM)bEnable);
+       }
+
+       void EnableScripting(BOOL bEnable = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ENABLESCRIPTING, 0, (LPARAM)bEnable);
+       }
+
+       void EnableShrink(BOOL bEnable = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ENABLESHRINK, 0, (LPARAM)bEnable);
+       }
+
+       void EndOfSource()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ENDOFSOURCE, 0, 0L);
+       }
+
+       void ImageFail(DWORD dwCookie)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_IMAGEFAIL, 0, (LPARAM)dwCookie);
+       }
+
+       int GetLayoutHeight() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, DTM_LAYOUTHEIGHT, 0, 0L);
+       }
+
+       int GetLayoutWidth() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, DTM_LAYOUTWIDTH, 0, 0L);
+       }
+
+       void Navigate(LPCTSTR pstrURL, UINT uFlags = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pstrURL);
+               ::SendMessage(m_hWnd, DTM_NAVIGATE, (WPARAM)uFlags, (LPARAM)pstrURL);
+       }
+
+       void SelectAll()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_SELECTALL, 0, 0L);
+       }
+
+       void SetImage(INLINEIMAGEINFO* pImageInfo)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pImageInfo);
+               ::SendMessage(m_hWnd, DTM_SETIMAGE, 0, (LPARAM)pImageInfo);
+       }
+
+       void ZoomLevel(int iLevel)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_ZOOMLEVEL, 0, (LPARAM)iLevel);
+       }
+
+#if (_WIN32_WCE >= 400)
+       void Stop()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DTM_STOP, 0, 0L);
+       }
+#endif // (_WIN32_WCE >= 400)
+
+       void GetScriptDispatch(IDispatch** ppDispatch)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(ppDispatch);
+               ATLASSERT(*ppDispatch==NULL);
+               ::SendMessage(m_hWnd, DTM_SCRIPTDISPATCH, 0, (LPARAM)ppDispatch);
+       }
+};
+
+typedef CHtmlCtrlT<ATL::CWindow> CHtmlCtrl;
+
+
+#ifdef WIN32_PLATFORM_PSPC
+
+///////////////////////////////////////////////////////////////////////////////
+// CRichInkCtrl
+
+template <class TBase>
+class CRichInkCtrlT : public TBase
+{
+public:
+// Constructors
+       CRichInkCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CRichInkCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+               ATLASSERT(hWnd != NULL);   // Did you remember to call InitRichInkDLL() ??
+               return hWnd;
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_RICHINK;
+       }
+
+       BOOL CanPaste(UINT uFormat = 0) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_CANPASTE, (WPARAM)uFormat, 0L);
+       }
+
+       BOOL CanRedo() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0L);
+       }
+
+       BOOL CanUndo() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L);
+       }
+
+       void ClearAll(BOOL bRepaint = TRUE) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_CLEARALL, (WPARAM)bRepaint, 0L);
+       }
+
+       BOOL GetModify() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L);
+       }
+
+       UINT GetPageStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_GETPAGESTYLE, 0, 0L);
+       }
+
+       UINT GetPenMode() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_GETPENMODE, 0, 0L);
+       }
+
+       UINT GetViewStyle() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_GETVIEW, 0, 0L);
+       }
+
+       UINT GetWrapMode() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_GETWRAPMODE, 0, 0L);
+       }
+
+       UINT GetZoomPercent() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_GETZOOMPERCENT, 0, 0L);
+       }
+
+       void InsertLinks(LPWSTR lpString, int cchLength = -1)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               if(cchLength == -1)
+                       cchLength = lstrlen(lpString);
+               ::SendMessage(m_hWnd, EM_INSERTLINKS, (WPARAM)cchLength, (LPARAM)lpString);
+       }
+
+       void RedoEvent()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_REDOEVENT, 0, 0L);
+       }
+
+       UINT SetInkLayer(UINT uLayer)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (UINT)::SendMessage(m_hWnd, EM_SETINKLAYER, (WPARAM)uLayer, 0L);
+       }
+
+       void SetPageStyle(UINT uStyle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETPAGESTYLE, (WPARAM)uStyle, 0L);
+       }
+
+       void SetPenMode(UINT uMode)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETPENMODE, (WPARAM)uMode, 0L);
+       }
+
+       void SetViewStyle(UINT uStyle)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETVIEW, (WPARAM)uStyle, 0L);
+       }
+
+       void SetViewAttributes(VIEWATTRIBUTES* pAttribs)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pAttribs);
+               ::SendMessage(m_hWnd, EM_SETVIEWATTRIBUTES, 0, (LPARAM)pAttribs);
+       }
+
+       void SetWrapMode(UINT uMode)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETWRAPMODE, (WPARAM)uMode, 0L);
+       }
+
+       void SetZoomPercent(UINT uPercent)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETZOOMPERCENT, (WPARAM)uPercent, 0L);
+       }
+
+       LONG StreamIn(UINT uFormat, EDITSTREAM& es)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_STREAMIN, (WPARAM)uFormat, (LPARAM)&es);
+       }
+
+       LONG StreamOut(UINT uFormat, EDITSTREAM& es)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (LONG)::SendMessage(m_hWnd, EM_STREAMOUT, (WPARAM)uFormat, (LPARAM)&es);
+       }
+
+       void UndoEvent()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_UNDOEVENT, 0, 0L);
+       }
+
+// Standard EM_xxx messages
+       DWORD GetSel() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L);
+       }
+
+       void GetSel(int& nStartChar, int& nEndChar) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
+       }
+
+       void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM)bCanUndo, (LPARAM)lpszNewText);
+       }
+
+       void SetModify(BOOL bModified = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, EM_SETMODIFY, (WPARAM)bModified, 0L);
+       }
+
+       int GetTextLength() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0L);
+       }
+
+// Clipboard operations
+       void Clear()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
+       }
+
+       void Copy()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_COPY, 0, 0L);
+       }
+
+       void Cut()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_CUT, 0, 0L);
+       }
+
+       void Paste()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
+       }
+};
+
+typedef CRichInkCtrlT<ATL::CWindow> CRichInkCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CInkXCtrl
+
+template <class TBase>
+class CInkXCtrlT : public TBase
+{
+public:
+// Constructors
+       CInkXCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CInkXCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+               ATLASSERT(hWnd != NULL);   // Did you remember to call InitInkX() ??
+               return hWnd;
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_INKX;
+       }
+
+       static UINT GetHotRecordingMessage()
+       {
+               return ::RegisterWindowMessage(szHotRecording);
+       }
+
+       void ClearAll()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IM_CLEARALL, 0, 0L);
+       }
+
+       int GetData(BYTE* lpBuffer, INT cbBuffer) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpBuffer);
+               return (int)::SendMessage(m_hWnd, IM_GETDATA, (WPARAM)cbBuffer, (LPARAM)lpBuffer);
+       }
+
+       int GetDataLen() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, IM_GETDATALEN, 0, 0L);
+       }
+
+       CRichInkCtrl GetRichInk() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HWND)::SendMessage(m_hWnd, IM_GETRICHINK, 0, 0L);
+       }
+
+       BOOL IsRecording() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, IM_RECORDING, 0, 0L);
+       }
+
+       void ReInit()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IM_REINIT, 0, 0L);
+       }
+
+       void SetData(const BYTE* lpInkData, INT cbInkData)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(lpInkData);
+               ::SendMessage(m_hWnd, IM_SETDATA, (WPARAM)cbInkData, (LPARAM)lpInkData);
+       }
+
+       void VoicePlay()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IM_VOICE_PLAY, 0, 0L);
+       }
+
+       BOOL IsVoicePlaying() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, IM_VOICE_PLAYING, 0, 0L);
+       }
+
+       BOOL VoiceRecord()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, IM_VOICE_RECORD, 0, 0L);
+       }
+
+       void VoiceStop()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IM_VOICE_STOP, 0, 0L);
+       }
+
+       void ShowVoiceBar(BOOL bShow = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, IM_VOICEBAR, (WPARAM)bShow, 0L);
+       }
+};
+
+typedef CInkXCtrlT<ATL::CWindow> CInkXCtrl;
+
+#endif // WIN32_PLATFORM_PSPC
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CVoiceRecorderCtrl
+
+template <class TBase>
+class CVoiceRecorderCtrlT : public TBase
+{
+public:
+// Constructors
+       CVoiceRecorderCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CVoiceRecorderCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, const POINT pt, LPTSTR pstrFileName, UINT nID, DWORD dwStyle = 0)
+       {
+               ATLASSERT(pstrFileName != NULL);
+               CM_VOICE_RECORDER cmvr = { 0 };
+               cmvr.cb = sizeof(CM_VOICE_RECORDER);
+               cmvr.dwStyle = dwStyle;
+               cmvr.xPos = pt.x;
+               cmvr.yPos = pt.y;
+               cmvr.hwndParent = hWndParent;
+               cmvr.id = nID;
+               cmvr.lpszRecordFileName = pstrFileName;
+               m_hWnd = VoiceRecorder_Create(&cmvr);
+               return m_hWnd;
+       }
+
+       HWND Create(LPCM_VOICE_RECORDER pAttribs)
+       {
+               ATLASSERT(pAttribs);
+               m_hWnd = VoiceRecorder_Create(pAttribs);
+               return m_hWnd;
+       }
+
+// Attributes
+       void Record()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, VRM_RECORD, 0, 0L);
+       }
+
+       void Play()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, VRM_PLAY, 0, 0L);
+       }
+
+       void Stop()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, VRM_STOP, 0, 0L);
+       }
+
+       void Cancel()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, VRM_CANCEL, 0, 0L);
+       }
+
+       void Done()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, VRM_OK, 0, 0L);
+       }
+};
+
+typedef CVoiceRecorderCtrlT<ATL::CWindow> CVoiceRecorderCtrl;
+
+
+#ifdef WIN32_PLATFORM_PSPC
+
+///////////////////////////////////////////////////////////////////////////////
+// CDocListCtrl
+
+template <class TBase>
+class CDocListCtrlT : public TBase
+{
+public:
+// Attributes
+       DOCLISTCREATE m_dlc;
+       TCHAR m_szPath[MAX_PATH];
+
+// Constructors
+       CDocListCtrlT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CDocListCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, WORD wId, LPCTSTR pszFolder = NULL, LPCTSTR pstrFilter = NULL,
+                       WORD wFilterIndex = 0, DWORD dwFlags = DLF_SHOWEXTENSION)
+       {
+               ATLASSERT(pstrFilter != NULL);   // It seems to need a filter badly!!
+               ::ZeroMemory(&m_dlc, sizeof(DOCLISTCREATE));
+               ::ZeroMemory(m_szPath, sizeof(m_szPath));
+               if(pszFolder != NULL)
+                       ::lstrcpyn(m_szPath, pszFolder, MAX_PATH - 1);
+               m_dlc.dwStructSize = sizeof(DOCLISTCREATE);
+               m_dlc.hwndParent = hWndParent;
+               m_dlc.pszFolder = m_szPath;
+               m_dlc.pstrFilter = pstrFilter;
+               m_dlc.wFilterIndex = wFilterIndex;
+               m_dlc.wId = wId;
+               m_dlc.dwFlags = dwFlags;
+               m_hWnd = DocList_Create(&m_dlc);
+               return m_hWnd;
+       }
+
+       HWND Create(DOCLISTCREATE* pDlc)
+       {
+               m_dlc = *pDlc;
+               m_hWnd = DocList_Create(&m_dlc);
+               return m_hWnd;
+       }
+
+// Attributes
+       void DeleteSel()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DLM_DELETESEL, 0, 0L);
+       }
+
+       void DisableUpdates()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DLM_DISABLEUPDATES, 0, 0L);
+       }
+
+       void EnableUpdates()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DLM_ENABLEUPDATES, 0, 0L);
+       }
+
+       int GetFilterIndex() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, DLM_GETFILTERINDEX, 0, 0L);
+       }
+
+       int GetItemCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, DLM_GETITEMCOUNT, 0, 0L);
+       }
+
+       int GetNextItem(int iIndex, DWORD dwRelation = LVNI_ALL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, DLM_GETNEXTITEM, (WPARAM)iIndex, (LPARAM)dwRelation);
+       }
+
+       int GetFirstItem(DWORD dwRelation = LVNI_ALL) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, DLM_GETNEXTITEM, (WPARAM)-1, (LPARAM)dwRelation);
+       }
+
+       BOOL GetNextWave(int* pIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pIndex);
+               return (BOOL)::SendMessage(m_hWnd, DLM_GETNEXTWAVE, 0, (LPARAM)pIndex);
+       }
+
+       BOOL GetPrevWave(int* pIndex) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pIndex);
+               return (BOOL)::SendMessage(m_hWnd, DLM_GETPREVWAVE, 0, (LPARAM)pIndex);
+       }
+
+       int GetSelCount() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, DLM_GETSELCOUNT, 0, 0L);
+       }
+
+       BOOL GetSelPathName(LPTSTR pstrPath, int cchMax) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pstrPath);
+               return (BOOL)::SendMessage(m_hWnd, DLM_GETSELPATHNAME, (WPARAM)cchMax, (LPARAM)pstrPath);
+       }
+
+       void ReceiveIR(LPCTSTR pstrPath) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pstrPath);
+               ::SendMessage(m_hWnd, DLM_RECEIVEIR, 0, (LPARAM)pstrPath);
+       }
+
+       void Refresh()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DLM_REFRESH, 0, 0L);
+       }
+
+       BOOL RenameMoveSelectedItems()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, DLM_RENAMEMOVE, 0, 0L);
+       }
+
+       int SelectAll()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (int)::SendMessage(m_hWnd, DLM_SELECTALL, 0, 0L);
+       }
+
+       HRESULT SelectItem(LPCTSTR pstrPath, BOOL bVisible = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pstrPath);
+               return (HRESULT)::SendMessage(m_hWnd, DLM_SELECTITEM, (WPARAM)bVisible, (LPARAM)pstrPath);
+       }
+
+       void SendEMail(LPCTSTR pstrAttachment)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DLM_SENDEMAIL, 0, (LPARAM)pstrAttachment);
+       }
+
+       void SendIR(LPCTSTR pstrPath)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DLM_SENDIR, 0, (LPARAM)pstrPath);
+       }
+
+       HRESULT SetFilterIndex(int iIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HRESULT)::SendMessage(m_hWnd, DLM_SETFILTERINDEX, (WPARAM)iIndex, 0L);
+       }
+
+       void SetFolder(LPCTSTR pstrPath)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pstrPath);
+               ::SendMessage(m_hWnd, DLM_SETFOLDER, 0, (LPARAM)pstrPath);
+       }
+
+       BOOL SetItemState(int iIndex, const LVITEM* pItem)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pItem);
+               return (BOOL)::SendMessage(m_hWnd, DLM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)pItem);
+       }
+
+       BOOL SetItemState(int iIndex, UINT uState, UINT uMask)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               LV_ITEM lvi = { 0 };
+               lvi.stateMask = uMask;
+               lvi.state = uState;
+               return (BOOL)::SendMessage(m_hWnd, DLM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)&lvi);
+       }
+
+       void SetOneItem(int iIndex, LPCVOID pPA)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DLM_SETONEITEM, (WPARAM)iIndex, (LPARAM)pPA);
+       }
+
+       void SetSelect(int iIndex)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::SendMessage(m_hWnd, DLM_SETSELECT, (WPARAM)iIndex, 0L);
+       }
+
+       void SetSelPathName(LPCTSTR pstrPath)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pstrPath);
+               ::SendMessage(m_hWnd, DLM_SETSELPATHNAME, 0, (LPARAM)pstrPath);
+       }
+
+       BOOL SetSortOrder()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, DLM_SETSORTORDER, 0, 0L);
+       }
+
+       HRESULT Update()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (HRESULT)::SendMessage(m_hWnd, DLM_UPDATE, 0, 0L);
+       }
+
+       BOOL ValidateFolder()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return (BOOL)::SendMessage(m_hWnd, DLM_VALIDATEFOLDER, 0, 0L);
+       }
+
+// Functions
+       BOOL GetFirstSelectedWaveFile(int* pIndex, LPTSTR szPath, const size_t cchPath)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return DocList_GetFirstSelectedWaveFile(m_hWnd, pIndex, szPath, cchPath);
+       }
+
+       BOOL GetNextSelectedWaveFile(int* pIndex, LPTSTR szPath, const size_t cchPath)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return DocList_GetNextSelectedWaveFile(m_hWnd, pIndex, szPath, cchPath);
+       }
+};
+
+typedef CDocListCtrlT<ATL::CWindow> CDocListCtrl;
+
+#endif // WIN32_PLATFORM_PSPC
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CCapEdit
+
+template <class TBase>
+class CCapEditT : public TBase
+{
+public:
+// Constructors
+       CCapEditT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CCapEditT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               HWND hWnd = /*TBase*/CWindow::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+               ATLASSERT(hWnd != NULL);   // Did you remember to call SHInitExtraControls() ??
+               return hWnd;
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_CAPEDIT;
+       }
+};
+
+typedef CCapEditT<WTL::CEdit> CCapEdit;
+
+///////////////////////////////////////////////////////////////////////////////
+// CTTStatic
+
+#ifndef WIN32_PLATFORM_WFSP // Tooltips not supported on SmartPhone
+
+template <class TBase>
+class CTTStaticT : public TBase
+{
+public:
+// Constructors
+       CTTStaticT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CTTStaticT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               HWND hWnd = TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+               ATLASSERT(hWnd != NULL);   // Did you remember to call SHInitExtraControls() ??
+               return hWnd;
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_TSTATIC;
+       }
+
+// Operations
+       BOOL SetToolTipText(LPCTSTR pstrTipText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pstrTipText);
+               ATLASSERT(lstrlen(pstrTipText)<= 253);
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR pstr = buff.Allocate(lstrlen(pstrTipText) + 3);
+               if(pstr == NULL)
+                       return FALSE;
+               ::lstrcpy(pstr, _T("~~"));
+               ::lstrcat(pstr, pstrTipText);
+               return SetWindowText(pstr);
+       }
+};
+
+typedef CTTStaticT<WTL::CStatic> CTTStatic;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTTButton
+
+template <class TBase>
+class CTTButtonT : public TBase
+{
+public:
+// Constructors
+       CTTButtonT(HWND hWnd = NULL) : TBase(hWnd)
+       { }
+
+       CTTButtonT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               HWND hWnd = TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+               ATLASSERT(hWnd != NULL);   // Did you remember to call SHInitExtraControls() ??
+               return hWnd;
+       }
+
+// Attributes
+       static LPCTSTR GetWndClassName()
+       {
+               return WC_TBUTTON;
+       }
+
+// Operations
+       BOOL SetToolTipText(LPCTSTR pstrTipText)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ATLASSERT(pstrTipText);
+               ATLASSERT(lstrlen(pstrTipText)<= 253);
+               CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
+               LPTSTR pstr = buff.Allocate(lstrlen(pstrTipText) + 3);
+               if(pstr == NULL)
+                       return FALSE;
+               ::lstrcpy(pstr, _T("~~"));
+               ::lstrcat(pstr, pstrTipText);
+               return SetWindowText(pstr);
+       }
+};
+
+typedef CTTButtonT<WTL::CButton> CTTButton;
+
+#endif // !WIN32_PLATFORM_WFSP
+
+
+// --- SmartPhone specific controls ---
+
+#ifdef WIN32_PLATFORM_WFSP
+
+///////////////////////////////////////////////////////////////////////////////
+// CSpinCtrlT - CSpinCtrl : SmartPhone adapted UpDown control
+
+template <class TBase>
+class CSpinCtrlT : public CUpDownCtrlT< TBase >
+{
+public:
+// Constructors
+       CSpinCtrlT(HWND hWnd = NULL) : CUpDownCtrlT< TBase >(hWnd)
+       { }
+
+       CSpinCtrlT< TBase >& operator =(HWND hWnd)
+       {
+               m_hWnd = hWnd;
+               return *this;
+       }
+
+       HWND Create(HWND hWndParent, HWND hBuddy, DWORD dwStyle, int nID, LPCTSTR szExpandedName = NULL)
+       {
+               ATLASSERT(::IsWindow(hWndParent));
+               CUpDownCtrlT< TBase >::Create(hWndParent, NULL, szExpandedName, dwStyle, 0, nID, NULL);
+               ATLASSERT(m_hWnd != NULL);   // Did you remember to call AtlInitCommonControls(ICC_UPDOWN_CLASS)?
+               if (hBuddy != NULL)
+               {
+                       ATLASSERT(::IsWindow(hBuddy));
+                       SetBuddy(hBuddy);
+               }
+               return m_hWnd;
+       }
+};
+
+typedef CSpinCtrlT<ATL::CWindow> CSpinCtrl;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CSpinned - SmartPhone association of control and Spin
+
+template <class TBase, bool t_bExpandOnly>
+class CSpinned : public TBase
+{
+public:
+       CSpinCtrl m_SpinCtrl;
+       DWORD m_dwSpinnedStyle;
+
+// Constructors
+       CSpinned(HWND hWnd = NULL) : TBase(hWnd)
+       {
+               m_dwSpinnedStyle = WS_VISIBLE | UDS_ALIGNRIGHT | UDS_EXPANDABLE;
+               
+               if (t_bExpandOnly == true)
+                       m_dwSpinnedStyle |= UDS_NOSCROLL;
+               else
+                       m_dwSpinnedStyle |= UDS_HORZ | UDS_ARROWKEYS | UDS_SETBUDDYINT | UDS_WRAP;
+
+               if (hWnd != NULL)
+                       AttachOrCreateSpinCtrl();
+       }
+
+       CSpinned<TBase, t_bExpandOnly>& operator =(HWND hWnd)
+       {
+               Attach(hWnd);
+               return *this;
+       }
+
+       void Attach(HWND hWnd)
+       {
+               ATLASSERT(!IsWindow());
+               TBase* pT = static_cast<TBase*>(this);
+               pT->m_hWnd = hWnd;
+               if (hWnd != NULL)
+                       AttachOrCreateSpinCtrl();
+       }
+
+       HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szExpandedName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+
+               TBase* pT = static_cast<TBase*>(this);
+               TBase::Create(hWndParent, rect, NULL, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
+               ATLASSERT(pT->m_hWnd != NULL);
+
+               m_SpinCtrl.Create(hWndParent, pT->m_hWnd, m_dwSpinnedStyle, ATL_IDW_SPIN_ID + (int)MenuOrID.m_hMenu, szExpandedName);
+
+               ATLASSERT(m_SpinCtrl.m_hWnd != NULL);   // Did you remember to call AtlInitCommonControls(ICC_UPDOWN_CLASS)?
+
+               return pT->m_hWnd;
+       }
+
+// Attributes
+       CSpinCtrl& GetSpinCtrl()
+       {
+               return m_SpinCtrl;
+       }
+
+// Implementation
+       // Attach our existing SpinCtrl or create one
+       bool AttachOrCreateSpinCtrl()
+       {
+               TBase* pT = static_cast<TBase*>(this);
+
+               HWND hSpin = ::GetDlgItem(pT->GetParent(), ATL_IDW_SPIN_ID + pT->GetDlgCtrlID());
+
+               if (hSpin != NULL)
+               {
+                       m_SpinCtrl.Attach(hSpin);
+#ifdef DEBUG
+                       TCHAR sClassName[16];
+                       ::GetClassName(hSpin, sClassName, 16);
+                       ATLASSERT(!_tcscmp(sClassName, UPDOWN_CLASS));
+                       ATLASSERT(m_SpinCtrl.GetBuddy().m_hWnd == pT->m_hWnd);
+#endif // DEBUG
+               }
+               else
+               {
+                       m_SpinCtrl.Create(pT->GetParent(), pT->m_hWnd, m_dwSpinnedStyle, ATL_IDW_SPIN_ID + pT->GetDlgCtrlID());
+               }
+
+               return m_SpinCtrl.m_hWnd != NULL;
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CSpinListBox - SmartPhone spinned ListBox control
+// CExpandListBox - SmartPhone expandable ListBox control
+// CExpandEdit - SmartPhone expandable Edit control
+// CExpandCapEdit - SmartPhone expandable CapEdit control
+
+typedef CSpinned<CListBox, false>   CSpinListBox;
+typedef CSpinned<CListBox, true>    CExpandListBox;
+typedef CSpinned<CEdit, true>          CExpandEdit;
+typedef CSpinned<CCapEdit, true>    CExpandCapEdit;
+
+#endif // WIN32_PLATFORM_WFSP
+
+#endif // _WTL_CE_NO_CONTROLS
+
+}; // namespace WTL
+
+#endif // __ATLWINCE_H__
diff --git a/include/WTL/Include/atlwinx.h b/include/WTL/Include/atlwinx.h
new file mode 100644 (file)
index 0000000..a7e31d3
--- /dev/null
@@ -0,0 +1,529 @@
+// Windows Template Library - WTL version 8.1
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// This file is a part of the Windows Template Library.
+// The use and distribution terms for this software are covered by the
+// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
+// which can be found in the file CPL.TXT at the root of this distribution.
+// By using this software in any fashion, you are agreeing to be bound by
+// the terms of this license. You must not remove this notice, or
+// any other, from this software.
+
+#ifndef __ATLWINX_H__
+#define __ATLWINX_H__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error atlwinx.h requires atlapp.h to be included first
+#endif
+
+#if (_ATL_VER >= 0x0700)
+  #include <atlwin.h>
+#endif // (_ATL_VER >= 0x0700)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// _U_RECT
+// _U_MENUorID
+// _U_STRINGorID
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Command Chaining Macros
+
+#define CHAIN_COMMANDS(theChainClass) \
+       if(uMsg == WM_COMMAND) \
+               CHAIN_MSG_MAP(theChainClass)
+
+#define CHAIN_COMMANDS_ALT(theChainClass, msgMapID) \
+       if(uMsg == WM_COMMAND) \
+               CHAIN_MSG_MAP_ALT(theChainClass, msgMapID)
+
+#define CHAIN_COMMANDS_MEMBER(theChainMember) \
+       if(uMsg == WM_COMMAND) \
+               CHAIN_MSG_MAP_MEMBER(theChainMember)
+
+#define CHAIN_COMMANDS_ALT_MEMBER(theChainMember, msgMapID) \
+       if(uMsg == WM_COMMAND) \
+               CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros for parent message map to selectively reflect control messages
+
+// NOTE: ReflectNotifications is a member of ATL's CWindowImplRoot
+//  (and overridden in 2 cases - CContainedWindowT and CAxHostWindow)
+//  Since we can't modify ATL, we'll provide the needed additions
+//  in a separate function (that is not a member of CWindowImplRoot)
+
+namespace WTL
+{
+
+inline LRESULT WtlReflectNotificationsFiltered(HWND hWndParent, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled,
+                                               UINT uMsgFilter = WM_NULL, UINT_PTR idFromFilter = 0, HWND hWndChildFilter = NULL)
+{
+       if((uMsgFilter != WM_NULL) && (uMsgFilter != uMsg))
+       {
+               // The notification message doesn't match the filter.
+               bHandled = FALSE;
+               return 1;
+       }
+
+       HWND hWndChild = NULL;
+       UINT_PTR idFrom = 0;
+
+       switch(uMsg)
+       {
+       case WM_COMMAND:
+               if(lParam != NULL)      // not from a menu
+               {
+                       hWndChild = (HWND)lParam;
+                       idFrom = (UINT_PTR)LOWORD(wParam);
+               }
+               break;
+       case WM_NOTIFY:
+               hWndChild = ((LPNMHDR)lParam)->hwndFrom;
+               idFrom = ((LPNMHDR)lParam)->idFrom;
+               break;
+#ifndef _WIN32_WCE
+       case WM_PARENTNOTIFY:
+               switch(LOWORD(wParam))
+               {
+               case WM_CREATE:
+               case WM_DESTROY:
+                       hWndChild = (HWND)lParam;
+                       idFrom = (UINT_PTR)HIWORD(wParam);
+                       break;
+               default:
+                       hWndChild = ::GetDlgItem(hWndParent, HIWORD(wParam));
+                       idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild);
+                       break;
+               }
+               break;
+#endif // !_WIN32_WCE
+       case WM_DRAWITEM:
+               if(wParam)      // not from a menu
+               {
+                       hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
+                       idFrom = (UINT_PTR)wParam;
+               }
+               break;
+       case WM_MEASUREITEM:
+               if(wParam)      // not from a menu
+               {
+                       hWndChild = ::GetDlgItem(hWndParent, ((LPMEASUREITEMSTRUCT)lParam)->CtlID);
+                       idFrom = (UINT_PTR)wParam;
+               }
+               break;
+       case WM_COMPAREITEM:
+               if(wParam)      // not from a menu
+               {
+                       hWndChild = ((LPCOMPAREITEMSTRUCT)lParam)->hwndItem;
+                       idFrom = (UINT_PTR)wParam;
+               }
+               break;
+       case WM_DELETEITEM:
+               if(wParam)      // not from a menu
+               {
+                       hWndChild = ((LPDELETEITEMSTRUCT)lParam)->hwndItem;
+                       idFrom = (UINT_PTR)wParam;
+               }
+               break;
+       case WM_VKEYTOITEM:
+       case WM_CHARTOITEM:
+       case WM_HSCROLL:
+       case WM_VSCROLL:
+               hWndChild = (HWND)lParam;
+               idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild);
+               break;
+       case WM_CTLCOLORBTN:
+       case WM_CTLCOLORDLG:
+       case WM_CTLCOLOREDIT:
+       case WM_CTLCOLORLISTBOX:
+       case WM_CTLCOLORMSGBOX:
+       case WM_CTLCOLORSCROLLBAR:
+       case WM_CTLCOLORSTATIC:
+               hWndChild = (HWND)lParam;
+               idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild);
+               break;
+       default:
+               break;
+       }
+
+       if((hWndChild == NULL) ||
+               ((hWndChildFilter != NULL) && (hWndChildFilter != hWndChild)))
+       {
+               // Either hWndChild isn't valid, or
+               // hWndChild doesn't match the filter.
+               bHandled = FALSE;
+               return 1;
+       }
+
+       if((idFromFilter != 0) && (idFromFilter != idFrom))
+       {
+               // The dialog control id doesn't match the filter.
+               bHandled = FALSE;
+               return 1;
+       }
+
+       ATLASSERT(::IsWindow(hWndChild));
+       LRESULT lResult = ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
+       if((lResult == 0) && (uMsg >= WM_CTLCOLORMSGBOX) && (uMsg <= WM_CTLCOLORSTATIC))
+       {
+               // Try to prevent problems with WM_CTLCOLOR* messages when
+               // the message wasn't really handled
+               bHandled = FALSE;
+       }
+
+       return lResult;
+}
+
+}; // namespace WTL
+
+// Try to prevent problems with WM_CTLCOLOR* messages when
+// the message wasn't really handled
+#define REFLECT_NOTIFICATIONS_EX() \
+{ \
+       bHandled = TRUE; \
+       lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+       if((lResult == 0) && (uMsg >= WM_CTLCOLORMSGBOX) && (uMsg <= WM_CTLCOLORSTATIC)) \
+               bHandled = FALSE; \
+       if(bHandled) \
+               return TRUE; \
+}
+
+#define REFLECT_NOTIFICATIONS_MSG_FILTERED(uMsgFilter) \
+       { \
+               bHandled = TRUE; \
+               lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, 0, NULL); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFICATIONS_ID_FILTERED(idFromFilter) \
+       { \
+               bHandled = TRUE; \
+               lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, WM_NULL, idFromFilter, NULL); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFICATIONS_HWND_FILTERED(hWndChildFilter) \
+       { \
+               bHandled = TRUE; \
+               lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, WM_NULL, 0, hWndChildFilter); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFICATIONS_MSG_ID_FILTERED(uMsgFilter, idFromFilter) \
+       { \
+               bHandled = TRUE; \
+               lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, idFromFilter, NULL); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFICATIONS_MSG_HWND_FILTERED(uMsgFilter, hWndChildFilter) \
+       { \
+               bHandled = TRUE; \
+               lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, 0, hWndChildFilter); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_COMMAND(id, code) \
+       if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_COMMAND_ID(id) \
+       if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_COMMAND_CODE(code) \
+       if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_COMMAND_RANGE(idFirst, idLast) \
+       if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst  && LOWORD(wParam) <= idLast) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_COMMAND_RANGE_CODE(idFirst, idLast, code) \
+       if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst  && LOWORD(wParam) <= idLast) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFY(id, cd) \
+       if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFY_ID(id) \
+       if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFY_CODE(cd) \
+       if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFY_RANGE(idFirst, idLast) \
+       if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECT_NOTIFY_RANGE_CODE(idFirst, idLast, cd) \
+       if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
+       { \
+               bHandled = TRUE; \
+               lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Reflected message handler macros for message maps (for ATL 3.0)
+
+#if (_ATL_VER < 0x0700)
+
+#define REFLECTED_COMMAND_HANDLER(id, code, func) \
+       if(uMsg == OCM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
+       { \
+               bHandled = TRUE; \
+               lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_COMMAND_ID_HANDLER(id, func) \
+       if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \
+       { \
+               bHandled = TRUE; \
+               lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_COMMAND_CODE_HANDLER(code, func) \
+       if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \
+       { \
+               bHandled = TRUE; \
+               lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
+       if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst  && LOWORD(wParam) <= idLast) \
+       { \
+               bHandled = TRUE; \
+               lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \
+       if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst  && LOWORD(wParam) <= idLast) \
+       { \
+               bHandled = TRUE; \
+               lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_NOTIFY_HANDLER(id, cd, func) \
+       if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
+       { \
+               bHandled = TRUE; \
+               lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_NOTIFY_ID_HANDLER(id, func) \
+       if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
+       { \
+               bHandled = TRUE; \
+               lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_NOTIFY_CODE_HANDLER(cd, func) \
+       if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
+       { \
+               bHandled = TRUE; \
+               lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \
+       if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
+       { \
+               bHandled = TRUE; \
+               lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \
+       if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
+       { \
+               bHandled = TRUE; \
+               lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+#endif // (_ATL_VER < 0x0700)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Dual argument helper classes (for ATL 3.0)
+
+#if (_ATL_VER < 0x0700)
+
+namespace ATL
+{
+
+class _U_RECT
+{
+public:
+       _U_RECT(LPRECT lpRect) : m_lpRect(lpRect)
+       { }
+       _U_RECT(RECT& rc) : m_lpRect(&rc)
+       { }
+       LPRECT m_lpRect;
+};
+
+class _U_MENUorID
+{
+public:
+       _U_MENUorID(HMENU hMenu) : m_hMenu(hMenu)
+       { }
+       _U_MENUorID(UINT nID) : m_hMenu((HMENU)LongToHandle(nID))
+       { }
+       HMENU m_hMenu;
+};
+
+class _U_STRINGorID
+{
+public:
+       _U_STRINGorID(LPCTSTR lpString) : m_lpstr(lpString)
+       { }
+       _U_STRINGorID(UINT nID) : m_lpstr(MAKEINTRESOURCE(nID))
+       { }
+       LPCTSTR m_lpstr;
+};
+
+}; // namespace ATL
+
+#endif // (_ATL_VER < 0x0700)
+
+
+namespace WTL
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward notifications support for message maps (for ATL 3.0)
+
+#if (_ATL_VER < 0x0700)
+
+// forward notifications support
+#define FORWARD_NOTIFICATIONS() \
+       { \
+               bHandled = TRUE; \
+               lResult = WTL::Atl3ForwardNotifications(m_hWnd, uMsg, wParam, lParam, bHandled); \
+               if(bHandled) \
+                       return TRUE; \
+       }
+
+static LRESULT Atl3ForwardNotifications(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+       LRESULT lResult = 0;
+       switch(uMsg)
+       {
+       case WM_COMMAND:
+       case WM_NOTIFY:
+#ifndef _WIN32_WCE
+       case WM_PARENTNOTIFY:
+#endif // !_WIN32_WCE
+       case WM_DRAWITEM:
+       case WM_MEASUREITEM:
+       case WM_COMPAREITEM:
+       case WM_DELETEITEM:
+       case WM_VKEYTOITEM:
+       case WM_CHARTOITEM:
+       case WM_HSCROLL:
+       case WM_VSCROLL:
+       case WM_CTLCOLORBTN:
+       case WM_CTLCOLORDLG:
+       case WM_CTLCOLOREDIT:
+       case WM_CTLCOLORLISTBOX:
+       case WM_CTLCOLORMSGBOX:
+       case WM_CTLCOLORSCROLLBAR:
+       case WM_CTLCOLORSTATIC:
+               lResult = ::SendMessage(::GetParent(hWnd), uMsg, wParam, lParam);
+               break;
+       default:
+               bHandled = FALSE;
+               break;
+       }
+       return lResult;
+}
+
+#endif // (_ATL_VER < 0x0700)
+
+}; // namespace WTL
+
+#endif // __ATLWINX_H__
diff --git a/include/WTL/Samples/Aero/AboutDlg.h b/include/WTL/Samples/Aero/AboutDlg.h
new file mode 100644 (file)
index 0000000..150a827
--- /dev/null
@@ -0,0 +1,47 @@
+// aboutdlg.h : interface of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CAboutDlg : public CAeroDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTBOX };
+
+       CAeroStatic m_Icon, m_Text;
+       CAeroButton m_OK;
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               CHAIN_MSG_MAP(CAeroDialogImpl<CAboutDlg>)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+
+               //MARGINS m = {7, 7, 7, 7};
+               MARGINS m = {-1};
+               SetMargins(m);
+
+               m_Icon.SubclassWindow(GetDlgItem(IDC_APPICON));
+               m_Text.SubclassWindow(GetDlgItem(IDC_TEXT));
+               m_OK.SubclassWindow(GetDlgItem(IDOK));
+
+               return TRUE;
+       }
+
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/Aero/Aero.cpp b/include/WTL/Samples/Aero/Aero.cpp
new file mode 100644 (file)
index 0000000..b61dae1
--- /dev/null
@@ -0,0 +1,64 @@
+// Aero.cpp : main source file for Aero.exe
+//
+
+#include "stdafx.h"
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+#include <atlctrlw.h>
+#include <atltheme.h>
+
+#include "resource.h"
+
+#include "Aero.h"
+#include "AeroView.h"
+#include "aboutdlg.h"
+#include "MainFrm.h"
+
+CAppModule _Module;
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       CMainFrame wndMain;
+
+       if(wndMain.CreateEx() == NULL)
+       {
+               ATLTRACE(_T("Main window creation failed!\n"));
+               return 0;
+       }
+
+       wndMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+       HRESULT hRes = ::CoInitialize(NULL);
+// If you are running on NT 4.0 or higher you can use the following call instead to 
+// make the EXE free threaded. This means that calls come in on a random RPC thread.
+//     HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
+       ::DefWindowProc(NULL, 0, 0, 0L);
+
+       AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);      // add flags to support other controls
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       int nRet = Run(lpstrCmdLine, nCmdShow);
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/Samples/Aero/Aero.h b/include/WTL/Samples/Aero/Aero.h
new file mode 100644 (file)
index 0000000..4408516
--- /dev/null
@@ -0,0 +1,381 @@
+// Aero.h
+//
+//  Aero sample support classes
+
+#ifndef __AERO_H__
+#define __AERO_H__
+
+#pragma once
+
+#if !defined _WTL_VER || _WTL_VER < 0x800
+       #error Aero.h requires the Windows Template Library 8.0
+#endif
+
+#if _WIN32_WINNT < 0x0600
+       #error Aero.h requires _WIN32_WINNT >= 0x0600
+#elif !defined(NTDDI_VERSION) || (NTDDI_VERSION < NTDDI_LONGHORN)
+       #error Aero.h requires the Windows Vista SDK
+#endif
+
+#ifndef __ATLTHEME_H__
+       #include "atltheme.h"
+#endif
+
+#include <dwmapi.h>
+#pragma comment (lib, "dwmapi.lib")
+
+#if (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD)
+  #pragma comment(lib, "delayimp.lib")
+  #pragma comment(linker, "/delayload:dwmapi.dll")
+#endif // (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes in this file:
+//
+// CAeroImpl<T> - enables Aero translucency (when available) for any window
+// CAeroDialogImpl<T, TBase> - dialog implementation of Aero translucency (when available)
+// CAeroFrameImpl<T, TBase, TWinTraits> - frame implementation of Aero translucency (when available) 
+// CAeroCtrlImpl - base implementation of Aero opacity for controls
+// CAeroStatic - Aero opaque Static control
+// CAeroButton - Aero opaque Button control
+// CAeroEdit - Aero opaque Edit control
+
+namespace WTL
+{
+
+template <class T>
+class CAeroImpl :
+       public CBufferedPaintImpl<T>,
+       public CThemeImpl<T>
+{
+public:
+       CAeroImpl(LPCWSTR lpstrThemeClassList = L"globals") 
+       {
+               m_PaintParams.dwFlags = BPPF_ERASE;
+
+               SetThemeClassList(lpstrThemeClassList);
+               MARGINS m = {0};
+               m_Margins = m;
+       }
+
+       static bool IsAeroSupported() 
+       {
+               return IsBufferedPaintSupported();
+       }
+
+       bool IsCompositionEnabled() const
+       {
+               BOOL bEnabled = FALSE;
+               return IsAeroSupported() ? SUCCEEDED(DwmIsCompositionEnabled(&bEnabled)) && bEnabled : false;
+       }    
+       
+       bool IsTheming() const
+       {
+               return m_hTheme != 0;
+       }    
+       
+       MARGINS m_Margins;
+
+       bool SetMargins(MARGINS& m)
+       {
+               m_Margins = m;
+               T* pT = static_cast<T*>(this);
+               return pT->IsWindow() && IsAeroSupported() ? SUCCEEDED(DwmExtendFrameIntoClientArea(pT->m_hWnd, &m_Margins)) : true;
+       }
+
+// implementation
+       void DoPaint(CDCHandle dc, RECT& rDest)
+       {
+               T* pT = static_cast<T*>(this);
+
+               RECT rClient;
+               pT->GetClientRect(&rClient);
+
+               RECT rView = {rClient.left + m_Margins.cxLeftWidth, rClient.top + m_Margins.cyTopHeight, 
+                       rClient.right - m_Margins.cxRightWidth, rClient.bottom - m_Margins.cyBottomHeight};
+
+               if (IsCompositionEnabled())
+                               dc.FillSolidRect(&rClient, RGB(0, 0, 0));
+               else
+                       if (IsTheming())
+                               pT->DrawThemeBackground(dc, WP_FRAMEBOTTOM, pT->m_hWnd == GetFocus() ? 1 : 2, &rClient, &rDest);
+                       else
+                               dc.FillSolidRect(&rClient, GetSysColor(COLOR_MENUBAR));
+
+               if (m_Margins.cxLeftWidth != -1)
+                       dc.FillSolidRect(&rView, GetSysColor(COLOR_WINDOW));
+               else 
+                       ::SetRectEmpty(&rView);
+
+               pT->AeroDoPaint(dc, rClient, rView, rDest);
+       }
+
+       void AeroDrawText(HDC dc, LPCTSTR pStr, LPRECT prText, UINT uFormat, DTTOPTS &dto)
+       {
+        if(IsTheming())
+                       if (IsAeroSupported())
+                               DrawThemeTextEx (dc, TEXT_BODYTITLE, 0, pStr, -1, uFormat, prText, &dto );
+                       else
+                               DrawThemeText(dc, TEXT_BODYTITLE, 0, pStr, -1, uFormat, 0, prText);
+               else
+                       CDCHandle(dc).DrawText(pStr, -1, prText, uFormat);
+       }
+
+       void AeroDrawText(HDC dc, LPCTSTR pStr, LPRECT prText, UINT uFormat, DWORD dwFlags, int iGlowSize)
+       {
+               DTTOPTS dto = { sizeof(DTTOPTS) };
+               dto.dwFlags = dwFlags;
+               dto.iGlowSize = iGlowSize;
+               AeroDrawText(dc, pStr, prText, uFormat, dto);
+       }
+
+// overridable
+       void AeroDoPaint(CDCHandle dc, RECT& rClient, RECT& rView, RECT& rDest)
+       {}
+
+       BEGIN_MSG_MAP(CAeroImpl)
+               CHAIN_MSG_MAP(CThemeImpl<T>)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
+        MESSAGE_HANDLER(WM_DWMCOMPOSITIONCHANGED, OnCompositionChanged)
+               MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient)
+               CHAIN_MSG_MAP(CBufferedPaintImpl<T>)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if (IsThemingSupported())
+                       OpenThemeData();
+
+               if (IsCompositionEnabled())
+                       DwmExtendFrameIntoClientArea(static_cast<T*>(this)->m_hWnd, &m_Margins);
+               return bHandled = FALSE;
+       }
+
+       LRESULT OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if (!IsCompositionEnabled() && IsTheming())
+                       static_cast<T*>(this)->Invalidate(FALSE);
+               return bHandled = FALSE;
+       }
+
+       LRESULT OnCompositionChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if (IsCompositionEnabled())
+                       SetMargins(m_Margins);
+               return 0;
+       }
+
+       LRESULT OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               T* pT = static_cast<T*>(this);
+               return ::DefWindowProc(pT->m_hWnd, uMsg, wParam, lParam);
+       }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroDialogImpl - dialog implementation of Aero translucency (when available)
+
+template <class T, class TBase  = CWindow>
+class ATL_NO_VTABLE CAeroDialogImpl : public CDialogImpl<T, TBase>, public CAeroImpl<T>
+{
+public:
+       CAeroDialogImpl(LPCWSTR lpstrThemeClassList = L"dialog") : CAeroImpl(lpstrThemeClassList)
+       {}
+
+       void AeroDoPaint(CDCHandle dc, RECT& rClient, RECT& rView, RECT& rDest)
+       {
+               if (!::IsRectEmpty(&rView))
+               {
+                       if (IsTheming())
+                               DrawThemeBackground(dc, WP_DIALOG, 1, &rView, &rDest);
+                       else
+                               dc.FillSolidRect(&rView, GetSysColor(COLOR_BTNFACE));
+               }
+       }
+
+       BEGIN_MSG_MAP(CAeroDialogImpl)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               CHAIN_MSG_MAP(CAeroImpl<T>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if (IsThemingSupported())
+               {
+                       OpenThemeData();
+                       EnableThemeDialogTexture(ETDT_ENABLE);
+               }
+
+               if (IsCompositionEnabled())
+                       DwmExtendFrameIntoClientArea(static_cast<T*>(this)->m_hWnd, &m_Margins);
+
+               return bHandled = FALSE;
+       }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroFrameImpl - frame implementation of Aero translucency (when available)
+
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
+class ATL_NO_VTABLE CAeroFrameImpl : 
+       public CFrameWindowImpl<T, TBase, TWinTraits>,
+       public CAeroImpl<T>
+{
+       typedef CFrameWindowImpl<T, TBase, TWinTraits> _baseClass;
+public:
+       CAeroFrameImpl(LPCWSTR lpstrThemeClassList = L"window") : CAeroImpl(lpstrThemeClassList)
+       {}
+
+       void UpdateLayout(BOOL bResizeBars = TRUE)
+       {
+               RECT rect = { 0 };
+               GetClientRect(&rect);
+
+               // position margins
+               if (m_Margins.cxLeftWidth != -1)
+               {
+                       rect.left += m_Margins.cxLeftWidth;
+                       rect.top += m_Margins.cyTopHeight;
+                       rect.right -= m_Margins.cxRightWidth;
+                       rect.bottom -= m_Margins.cyBottomHeight;
+               }
+
+               // position bars and offset their dimensions
+               UpdateBarsPosition(rect, bResizeBars);
+
+               // resize client window
+               if(m_hWndClient != NULL)
+                       ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
+                               rect.right - rect.left, rect.bottom - rect.top,
+                               SWP_NOZORDER | SWP_NOACTIVATE);
+
+               Invalidate(FALSE);
+       }
+
+       void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE)
+       {
+               // resize toolbar
+               if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE))
+               {
+                       RECT rectTB = { 0 };
+                       ::GetWindowRect(m_hWndToolBar, &rectTB);
+                       if(bResizeBars)
+                       {
+                               ::SetWindowPos(m_hWndToolBar, NULL, rect.left, rect.top,
+                                       rect.right - rect.left, rectTB.bottom - rectTB.top,
+                                       SWP_NOZORDER | SWP_NOACTIVATE);
+                               ::InvalidateRect(m_hWndToolBar, NULL, FALSE);
+                       }
+                       rect.top += rectTB.bottom - rectTB.top;
+               }
+
+               // resize status bar
+               if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
+               {
+                       RECT rectSB = { 0 };
+                       ::GetWindowRect(m_hWndStatusBar, &rectSB);
+                       rect.bottom -= rectSB.bottom - rectSB.top;
+                       if(bResizeBars)
+                               ::SetWindowPos(m_hWndStatusBar, NULL, rect.left, rect.bottom,
+                                       rect.right - rect.left, rectSB.bottom - rectSB.top,
+                                       SWP_NOZORDER | SWP_NOACTIVATE);
+               }
+       }
+
+       BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS , UINT nID = ATL_IDW_STATUS_BAR)
+       {
+               ATLASSERT(!::IsWindow(m_hWndStatusBar));
+               m_hWndStatusBar = ::CreateStatusWindow(dwStyle | CCS_NOPARENTALIGN , lpstrText, m_hWnd, nID);
+               return (m_hWndStatusBar != NULL);
+       }
+
+       BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS , UINT nID = ATL_IDW_STATUS_BAR)
+       {
+               const int cchMax = 128;   // max text length is 127 for status bars (+1 for null)
+               TCHAR szText[cchMax];
+               szText[0] = 0;
+               ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
+               return CreateSimpleStatusBar(szText, dwStyle, nID);
+       }
+
+       static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               return _baseClass::CreateSimpleReBarCtrl(hWndParent, dwStyle | CCS_NOPARENTALIGN, nID);
+       }
+
+       BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
+       {
+               ATLASSERT(!::IsWindow(m_hWndToolBar));
+               m_hWndToolBar = _baseClass::CreateSimpleReBarCtrl(m_hWnd, dwStyle | CCS_NOPARENTALIGN, nID);
+               return (m_hWndToolBar != NULL);
+       }
+
+       BEGIN_MSG_MAP(CAeroFrameImpl)
+               CHAIN_MSG_MAP(CAeroImpl<T>)
+               CHAIN_MSG_MAP(_baseClass)
+       END_MSG_MAP()
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroCtrlImpl - implementation of Aero opacity for controls
+
+template <class TBase>
+class CAeroCtrlImpl : public CBufferedPaintWindowImpl<CAeroCtrlImpl<TBase>, TBase>
+{
+public:
+       DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
+
+       void DoBufferedPaint(CDCHandle dc, RECT& rect)
+       {
+               HDC hDCPaint = NULL;
+               if(IsBufferedPaintSupported())
+                       m_BufferedPaint.Begin(dc, &rect, m_dwFormat, &m_PaintParams, &hDCPaint);
+
+               if(hDCPaint != NULL)
+                       DoPaint(hDCPaint, rect);
+               else
+                       DoPaint(dc.m_hDC, rect);
+
+               if(IsBufferedPaintSupported() && !m_BufferedPaint.IsNull())
+               {
+                       m_BufferedPaint.MakeOpaque(&rect);
+                       m_BufferedPaint.End();
+               }
+       }
+
+       void DoPaint(CDCHandle dc, RECT& /*rect*/)
+       {
+               DefWindowProc(WM_PRINTCLIENT, (WPARAM)dc.m_hDC, PRF_CLIENT);
+       }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroStatic - Aero opaque Static control
+// CAeroButton - Aero opaque Button control
+
+typedef CAeroCtrlImpl<CStatic> CAeroStatic;
+typedef CAeroCtrlImpl<CButton> CAeroButton;
+
+///////////////////////////////////////////////////////////////////////////////
+// CAeroEdit - Aero opaque Edit control
+class CAeroEdit : public CAeroCtrlImpl<CEdit>
+{
+       BEGIN_MSG_MAP(CAeroEdit)
+        REFLECTED_COMMAND_CODE_HANDLER(EN_CHANGE, OnChange)
+               CHAIN_MSG_MAP(CAeroCtrlImpl<CEdit>)
+       END_MSG_MAP()
+
+       LRESULT OnChange(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled)
+       {
+        Invalidate(FALSE); 
+               return bHandled = FALSE;
+    } 
+};
+
+}; // namespace WTL
+
+#endif // __AERO_H__
diff --git a/include/WTL/Samples/Aero/Aero.sln b/include/WTL/Samples/Aero/Aero.sln
new file mode 100644 (file)
index 0000000..8ea4d75
--- /dev/null
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Aero", "Aero.vcproj", "{E61F1A7E-8066-48F0-85DD-355EF3ABB02E}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {E61F1A7E-8066-48F0-85DD-355EF3ABB02E}.Debug|Win32.ActiveCfg = Debug|Win32
+               {E61F1A7E-8066-48F0-85DD-355EF3ABB02E}.Debug|Win32.Build.0 = Debug|Win32
+               {E61F1A7E-8066-48F0-85DD-355EF3ABB02E}.Release|Win32.ActiveCfg = Release|Win32
+               {E61F1A7E-8066-48F0-85DD-355EF3ABB02E}.Release|Win32.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/Aero/AeroView.h b/include/WTL/Samples/Aero/AeroView.h
new file mode 100644 (file)
index 0000000..7162a5c
--- /dev/null
@@ -0,0 +1,35 @@
+// AeroView.h : interface of the CAeroView class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CAeroView : public CWindowImpl<CAeroView>
+{
+public:
+       DECLARE_WND_CLASS(NULL)
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               pMsg;
+               return FALSE;
+       }
+
+       BEGIN_MSG_MAP(CAeroView)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CPaintDC dc(m_hWnd);
+
+               //TODO: Add your drawing code here
+
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/Aero/MainFrm.h b/include/WTL/Samples/Aero/MainFrm.h
new file mode 100644 (file)
index 0000000..0066e92
--- /dev/null
@@ -0,0 +1,176 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CMainFrame : public CAeroFrameImpl<CMainFrame>, public CUpdateUI<CMainFrame>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       DECLARE_FRAME_WND_CLASS_EX(NULL, IDR_MAINFRAME, 0, -1)
+
+       CAeroView m_view;
+       CCommandBarCtrl m_CmdBar;
+
+       CFont m_Font;
+
+       void InitFont()
+       {
+               LOGFONT lf = {0};
+               if (IsTheming())
+               {
+                       GetThemeSysFont (TMT_MSGBOXFONT, &lf);
+               }
+               else
+               {
+                       NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) };
+                       SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false );
+                       lf = ncm.lfMessageFont;
+               }
+               lf.lfHeight *= 3;
+
+               ATLVERIFY(m_Font.CreateFontIndirect(&lf));
+       }
+
+       void AeroDoPaint(CDCHandle dc, RECT& rClient, RECT& rView, RECT& rectClip)
+       {
+               rClient.top = rView.bottom;
+
+               HFONT hOld = dc.SelectFont(m_Font);
+
+               AeroDrawText(dc, L"WTL is great with Aero", &rClient, 
+                       DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX, 
+                       DTT_COMPOSITED | DTT_GLOWSIZE, 20);
+
+               dc.SelectFont(hOld);
+       }
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+       }
+
+       virtual BOOL OnIdle()
+       {
+               UIUpdateToolBar();
+               return FALSE;
+       }
+
+       BEGIN_UPDATE_UI_MAP(CMainFrame)
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+       END_UPDATE_UI_MAP()
+
+       BEGIN_MSG_MAP(CMainFrame)
+               CHAIN_MSG_MAP(CAeroFrameImpl<CMainFrame>)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+       END_MSG_MAP()
+
+// Handler prototypes (uncomment arguments if needed):
+//     LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+//     LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+//     LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // create command bar window
+               HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+               // attach menu
+               m_CmdBar.AttachMenu(GetMenu());
+               // load command bar images
+               m_CmdBar.LoadImages(IDR_MAINFRAME);
+               // remove old menu
+               SetMenu(NULL);
+
+               HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+               CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+               AddSimpleReBarBand(hWndCmdBar);
+               AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+
+               CreateSimpleStatusBar();
+
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+
+               UIAddToolBar(hWndToolBar);
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+
+               // create margins and font
+               MARGINS m = {20, 20, 0, 100};
+               SetMargins(m);
+               InitFont();
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               return 0;
+       }
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               // unregister message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: add code to initialize document
+
+               return 0;
+       }
+
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               static BOOL bVisible = TRUE;    // initially visible
+               bVisible = !bVisible;
+               CReBarCtrl rebar = m_hWndToolBar;
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);       // toolbar is 2nd added band
+               rebar.ShowBand(nBandIndex, bVisible);
+               UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/Aero/res/Aero.ico b/include/WTL/Samples/Aero/res/Aero.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/Samples/Aero/res/Aero.ico differ
diff --git a/include/WTL/Samples/Aero/res/toolbar.bmp b/include/WTL/Samples/Aero/res/toolbar.bmp
new file mode 100644 (file)
index 0000000..60f7a16
Binary files /dev/null and b/include/WTL/Samples/Aero/res/toolbar.bmp differ
diff --git a/include/WTL/Samples/Aero/resource.h b/include/WTL/Samples/Aero/resource.h
new file mode 100644 (file)
index 0000000..112239f
--- /dev/null
@@ -0,0 +1,19 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Aero.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDC_APPICON                     1000
+#define IDC_TEXT                        1001
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32775
+#define _APS_NEXT_CONTROL_VALUE         1002
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/Aero/stdafx.cpp b/include/WTL/Samples/Aero/stdafx.cpp
new file mode 100644 (file)
index 0000000..e5c9aa4
--- /dev/null
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     Aero.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
diff --git a/include/WTL/Samples/Aero/stdafx.h b/include/WTL/Samples/Aero/stdafx.h
new file mode 100644 (file)
index 0000000..d811e3b
--- /dev/null
@@ -0,0 +1,29 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#pragma once
+
+// Change these values to use different versions
+#define WINVER         0x0600
+#define _WIN32_WINNT   0x0600
+#define _WIN32_IE      0x0700
+#define _RICHEDIT_VER  0x0200
+
+#include <atlbase.h>
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#include <atlwin.h>
+
+#if defined _M_IX86
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+  #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
diff --git a/include/WTL/Samples/Alpha/Alpha.cpp b/include/WTL/Samples/Alpha/Alpha.cpp
new file mode 100644 (file)
index 0000000..a788da0
--- /dev/null
@@ -0,0 +1,57 @@
+// Alpha.cpp : main source file for Alpha.exe
+//
+
+#include "stdafx.h"
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+#include <atlctrlw.h>
+#include <atlmisc.h>
+
+#include "resource.h"
+
+#include "View.h"
+#include "aboutdlg.h"
+#include "MainFrm.h"
+
+CAppModule _Module;
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       CMainFrame wndMain;
+
+       if(wndMain.CreateEx() == NULL)
+       {
+               ATLTRACE(_T("Main window creation failed!\n"));
+               return 0;
+       }
+
+       wndMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+       HRESULT hRes = ::CoInitialize(NULL);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       int nRet = Run(lpstrCmdLine, nCmdShow);
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/Samples/Alpha/Alpha.h b/include/WTL/Samples/Alpha/Alpha.h
new file mode 100644 (file)
index 0000000..197e5f6
--- /dev/null
@@ -0,0 +1 @@
+// Alpha.h
diff --git a/include/WTL/Samples/Alpha/Alpha.sln b/include/WTL/Samples/Alpha/Alpha.sln
new file mode 100644 (file)
index 0000000..7fabd85
--- /dev/null
@@ -0,0 +1,17 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Alpha", "Alpha.vcxproj", "{E7965B9C-405A-0B7F-D2A1-11144D016AEA}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {E7965B9C-405A-0B7F-D2A1-11144D016AEA}.Debug|Win32.ActiveCfg = Debug|Win32
+               {E7965B9C-405A-0B7F-D2A1-11144D016AEA}.Release|Win32.ActiveCfg = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/Alpha/Alpha.suo b/include/WTL/Samples/Alpha/Alpha.suo
new file mode 100644 (file)
index 0000000..d6bf70a
Binary files /dev/null and b/include/WTL/Samples/Alpha/Alpha.suo differ
diff --git a/include/WTL/Samples/Alpha/Alpha.vcxproj b/include/WTL/Samples/Alpha/Alpha.vcxproj
new file mode 100644 (file)
index 0000000..a5db936
--- /dev/null
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <SccProjectName />
+    <SccLocalPath />
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)Debug\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)Debug\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;STRICT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <StringPooling>true</StringPooling>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+      <PrecompiledHeaderOutputFile>.\Release/Alpha.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+      <ObjectFileName>.\Release/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+      <WarningLevel>Level4</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+    </ClCompile>
+    <Link>
+      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
+      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>.\Release/Alpha.exe</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <ProgramDatabaseFile>.\Release/Alpha.pdb</ProgramDatabaseFile>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Release/Alpha.tlb</TypeLibraryName>
+    </Midl>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;STRICT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+      <PrecompiledHeaderOutputFile>.\Debug/Alpha.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+      <ObjectFileName>.\Debug/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+      <WarningLevel>Level4</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
+      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>.\Debug/Alpha.exe</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>.\Debug/Alpha.pdb</ProgramDatabaseFile>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Debug/Alpha.tlb</TypeLibraryName>
+    </Midl>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="Alpha.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="Alpha.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="aboutdlg.h" />
+    <ClInclude Include="mainfrm.h" />
+    <ClInclude Include="resource.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="view.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\Alpha.ico" />
+    <None Include="res\toolbar.bmp" />
+    <None Include="res\toolbar_old.bmp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/Alpha/Alpha.vcxproj.filters b/include/WTL/Samples/Alpha/Alpha.vcxproj.filters
new file mode 100644 (file)
index 0000000..ad3b4ec
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{143404df-3fc9-45c5-9bd0-dd6b5218e443}</UniqueIdentifier>
+      <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{91944227-9f5a-4ba2-8316-a5221ace3237}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{6f508da1-e0d1-4f4c-a294-ed5c512005ea}</UniqueIdentifier>
+      <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Alpha.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="Alpha.rc">
+      <Filter>Source Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="aboutdlg.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="mainfrm.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="resource.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="view.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\Alpha.ico">
+      <Filter>Resource Files</Filter>
+    </None>
+    <None Include="res\toolbar.bmp">
+      <Filter>Resource Files</Filter>
+    </None>
+    <None Include="res\toolbar_old.bmp">
+      <Filter>Resource Files</Filter>
+    </None>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/Alpha/Alpha.vcxproj.user b/include/WTL/Samples/Alpha/Alpha.vcxproj.user
new file mode 100644 (file)
index 0000000..ace9a86
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/Alpha/aboutdlg.h b/include/WTL/Samples/Alpha/aboutdlg.h
new file mode 100644 (file)
index 0000000..90e1dda
--- /dev/null
@@ -0,0 +1,29 @@
+// aboutdlg.h : interface of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CAboutDlg : public CDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTBOX };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+               return TRUE;
+       }
+
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/Alpha/mainfrm.h b/include/WTL/Samples/Alpha/mainfrm.h
new file mode 100644 (file)
index 0000000..16b8252
--- /dev/null
@@ -0,0 +1,148 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
+
+       CView m_view;
+
+       CCommandBarCtrl m_CmdBar;
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+       }
+
+       virtual BOOL OnIdle()
+       {
+               UIUpdateToolBar();
+               return FALSE;
+       }
+
+       BEGIN_MSG_MAP(CMainFrame)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+               COMMAND_ID_HANDLER(ID_EDIT_CUT, OnEditCutOrCopy)
+               COMMAND_ID_HANDLER(ID_EDIT_COPY, OnEditCutOrCopy)
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
+               CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
+       END_MSG_MAP()
+
+       BEGIN_UPDATE_UI_MAP(CMainFrame)
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_EDIT_PASTE, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+       END_UPDATE_UI_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // Check if Common Controls 6.0 are used. If yes, use 32-bit (alpha) images
+               // for the toolbar and command bar. If not, use the old, 4-bit images.
+               UINT uResID = IDR_MAINFRAME_OLD;
+               DWORD dwMajor = 0;
+               DWORD dwMinor = 0;
+               HRESULT hRet = AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
+               if(SUCCEEDED(hRet) && dwMajor >= 6)
+                       uResID = IDR_MAINFRAME;
+
+               // Set values to be displayed in the view window
+               m_view.m_dwCommCtrlMajor = dwMajor;
+               m_view.m_dwCommCtrlMinor = dwMinor;
+               m_view.m_bAlpha = (uResID == IDR_MAINFRAME);
+
+               // create command bar window
+               HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+               // attach menu
+               m_CmdBar.AttachMenu(GetMenu());
+               // load command bar images
+               m_CmdBar.LoadImages(uResID);
+               // remove old menu
+               SetMenu(NULL);
+
+               HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, uResID, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+               CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+               AddSimpleReBarBand(hWndCmdBar);
+               AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+               CreateSimpleStatusBar();
+
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+
+               UIAddToolBar(hWndToolBar);
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               UIEnable(ID_EDIT_PASTE, FALSE);
+
+               return 0;
+       }
+
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // TODO: add code to initialize document
+
+               return 0;
+       }
+
+       LRESULT OnEditCutOrCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // Just to test enabled/disabled image state - toggle Paste button
+               static BOOL bEnabled = FALSE;
+               bEnabled = !bEnabled;
+               UIEnable(ID_EDIT_PASTE, bEnabled);
+               return 0;
+       }
+
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               static BOOL bVisible = TRUE;    // initially visible
+               bVisible = !bVisible;
+               CReBarCtrl rebar = m_hWndToolBar;
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);       // toolbar is 2nd added band
+               rebar.ShowBand(nBandIndex, bVisible);
+               UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/Alpha/readme.txt b/include/WTL/Samples/Alpha/readme.txt
new file mode 100644 (file)
index 0000000..9ff2bb1
--- /dev/null
@@ -0,0 +1,15 @@
+Alpha WTL Sample
+----------------
+
+This sample shows how to use 32-bit (alpha channel) images with toolbars and
+command bars. It also displays them only if running on Windows XP with themes
+enabled, while it displays standard 4-bit images in other cases.
+
+Cut and Copy commands toggle enable/disable state for the Paste command, just
+to show how images look disabled.
+
+Subdirectories Release and Debug contain the manifest file, alpha.exe.manifest
+which is required to use 32-bit (alpha) images. If you use Windows XP with
+themes, you can rename or delete the manifest file to disable alpha images.
+
+-end-
diff --git a/include/WTL/Samples/Alpha/res/Alpha.ico b/include/WTL/Samples/Alpha/res/Alpha.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/Samples/Alpha/res/Alpha.ico differ
diff --git a/include/WTL/Samples/Alpha/res/toolbar.bmp b/include/WTL/Samples/Alpha/res/toolbar.bmp
new file mode 100644 (file)
index 0000000..6d119d7
Binary files /dev/null and b/include/WTL/Samples/Alpha/res/toolbar.bmp differ
diff --git a/include/WTL/Samples/Alpha/res/toolbar_old.bmp b/include/WTL/Samples/Alpha/res/toolbar_old.bmp
new file mode 100644 (file)
index 0000000..60f7a16
Binary files /dev/null and b/include/WTL/Samples/Alpha/res/toolbar_old.bmp differ
diff --git a/include/WTL/Samples/Alpha/resource.h b/include/WTL/Samples/Alpha/resource.h
new file mode 100644 (file)
index 0000000..9038818
--- /dev/null
@@ -0,0 +1,18 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Alpha.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDR_MAINFRAME_OLD               129
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32772
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           102
+#endif
+#endif
diff --git a/include/WTL/Samples/Alpha/stdafx.cpp b/include/WTL/Samples/Alpha/stdafx.cpp
new file mode 100644 (file)
index 0000000..f924d3a
--- /dev/null
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     Alpha.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
diff --git a/include/WTL/Samples/Alpha/stdafx.h b/include/WTL/Samples/Alpha/stdafx.h
new file mode 100644 (file)
index 0000000..2549ada
--- /dev/null
@@ -0,0 +1,26 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__D895E823_4E73_4C58_95DF_B988F909018A__INCLUDED_)
+#define AFX_STDAFX_H__D895E823_4E73_4C58_95DF_B988F909018A__INCLUDED_
+
+// Change these values to use different versions
+#define WINVER         0x0500
+#define _WIN32_WINNT   0x0501
+#define _WIN32_IE      0x0501
+#define _RICHEDIT_VER  0x0100
+
+
+#include <atlbase.h>
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#include <atlwin.h>
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__D895E823_4E73_4C58_95DF_B988F909018A__INCLUDED_)
diff --git a/include/WTL/Samples/Alpha/view.h b/include/WTL/Samples/Alpha/view.h
new file mode 100644 (file)
index 0000000..bd42a50
--- /dev/null
@@ -0,0 +1,44 @@
+// View.h : interface of the CView class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CView : public CWindowImpl<CView>
+{
+public:
+       DECLARE_WND_CLASS(NULL)
+
+       DWORD m_dwCommCtrlMajor;
+       DWORD m_dwCommCtrlMinor;
+       bool m_bAlpha;
+
+       CView() :
+               m_dwCommCtrlMajor(0),
+               m_dwCommCtrlMinor(0),
+               m_bAlpha(false)
+       { }
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               pMsg;
+               return FALSE;
+       }
+
+       BEGIN_MSG_MAP(CView)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+       END_MSG_MAP()
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CPaintDC dc(m_hWnd);
+
+               CString strText;
+               strText.Format(_T("Common Controls version %u.%2.2u"), m_dwCommCtrlMajor, m_dwCommCtrlMinor);
+               dc.TextOut(10, 20, strText);
+
+               dc.TextOut(10, 40, m_bAlpha ? _T("Using 32-bit (alpha channel) images") : _T("Using standard 4-bit images"));
+
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/BmpView/BmpView.cpp b/include/WTL/Samples/BmpView/BmpView.cpp
new file mode 100644 (file)
index 0000000..4e0eb72
--- /dev/null
@@ -0,0 +1,85 @@
+// BmpView.cpp : main source file for BmpView.exe
+//
+
+#include "stdafx.h"
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#ifndef _WIN32_WCE
+#include <atlctrlw.h>
+#endif // _WIN32_WCE
+#include <atldlgs.h>
+#include <atlscrl.h>
+#include <atlmisc.h>
+#ifndef _WIN32_WCE
+#include <atlprint.h>
+#endif // _WIN32_WCE
+#include <atlcrack.h>
+
+#ifndef _WIN32_WCE
+#include "resource.h"
+#else // _WIN32_WCE
+#ifndef WIN32_PLATFORM_PSPC
+#include "resourcece.h"
+#else // WIN32_PLATFORM_PSPC
+#include "resourceppc.h"
+#endif // WIN32_PLATFORM_PSPC
+#endif // _WIN32_WCE
+
+#include "View.h"
+#include "props.h"
+#ifndef _WIN32_WCE
+#include "list.h"
+#endif // _WIN32_WCE
+#include "MainFrm.h"
+
+CAppModule _Module;
+
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = 
+#ifndef _WIN32_WCE
+               SW_SHOWDEFAULT
+#else // _WIN32_WCE
+               SW_SHOWNORMAL
+#endif // _WIN32_WCE
+               )
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       CMainFrame wndMain;
+
+       if(wndMain.CreateEx() == NULL)
+       {
+               ATLTRACE(_T("Main window creation failed!\n"));
+               return 0;
+       }
+
+       wndMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+#ifndef _WIN32_WCE
+       INITCOMMONCONTROLSEX iccx;
+       iccx.dwSize = sizeof(iccx);
+       iccx.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
+       BOOL bRet = ::InitCommonControlsEx(&iccx);
+       bRet;
+       ATLASSERT(bRet);
+#endif // _WIN32_WCE
+
+       HRESULT hRes = _Module.Init(NULL, hInstance);
+       hRes;
+       ATLASSERT(SUCCEEDED(hRes));
+
+       int nRet = Run(lpstrCmdLine, nCmdShow);
+
+       _Module.Term();
+       return nRet;
+}
diff --git a/include/WTL/Samples/BmpView/BmpView.sln b/include/WTL/Samples/BmpView/BmpView.sln
new file mode 100644 (file)
index 0000000..b679c1d
--- /dev/null
@@ -0,0 +1,17 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BmpView", "BmpView.vcxproj", "{C9960F2A-8E92-B9DB-8C7E-4B82F34BD425}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {C9960F2A-8E92-B9DB-8C7E-4B82F34BD425}.Debug|Win32.ActiveCfg = Debug|Win32
+               {C9960F2A-8E92-B9DB-8C7E-4B82F34BD425}.Release|Win32.ActiveCfg = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/BmpView/BmpView.suo b/include/WTL/Samples/BmpView/BmpView.suo
new file mode 100644 (file)
index 0000000..f9cd09e
Binary files /dev/null and b/include/WTL/Samples/BmpView/BmpView.suo differ
diff --git a/include/WTL/Samples/BmpView/BmpView.vcxproj b/include/WTL/Samples/BmpView/BmpView.vcxproj
new file mode 100644 (file)
index 0000000..c83a7b4
--- /dev/null
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <SccProjectName />
+    <SccLocalPath />
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;STRICT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+      <PrecompiledHeaderOutputFile>.\Debug/BmpView.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+      <ObjectFileName>.\Debug/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+      <WarningLevel>Level4</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
+      <AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>.\Debug/BmpView.exe</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>.\Debug/BmpView.pdb</ProgramDatabaseFile>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Debug/BmpView.tlb</TypeLibraryName>
+    </Midl>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+      <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+      <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;STRICT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <StringPooling>true</StringPooling>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+      <PrecompiledHeaderOutputFile>.\Release/BmpView.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+      <ObjectFileName>.\Release/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+      <WarningLevel>Level4</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
+      <AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>.\Release/BmpView.exe</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <ProgramDatabaseFile>.\Release/BmpView.pdb</ProgramDatabaseFile>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Release/BmpView.tlb</TypeLibraryName>
+    </Midl>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+      <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="BmpView.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="BmpView.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="list.h" />
+    <ClInclude Include="mainfrm.h" />
+    <ClInclude Include="props.h" />
+    <ClInclude Include="resource.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="view.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\BmpView.exe.manifest" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\BmpView.ico" />
+    <None Include="res\toolbar.bmp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/BmpView/BmpView.vcxproj.filters b/include/WTL/Samples/BmpView/BmpView.vcxproj.filters
new file mode 100644 (file)
index 0000000..c43b85b
--- /dev/null
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{eea582ad-e0ba-488c-9b3d-32fb39e31f9d}</UniqueIdentifier>
+      <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{e999610a-fd94-4d5d-bf56-e679a01002f3}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{e9d46f3d-57e7-4304-af54-a5d455fb9747}</UniqueIdentifier>
+      <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="BmpView.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="BmpView.rc">
+      <Filter>Source Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="list.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="mainfrm.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="props.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="resource.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="view.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\BmpView.exe.manifest">
+      <Filter>Resource Files</Filter>
+    </Manifest>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\BmpView.ico">
+      <Filter>Resource Files</Filter>
+    </None>
+    <None Include="res\toolbar.bmp">
+      <Filter>Resource Files</Filter>
+    </None>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/BmpView/BmpView.vcxproj.user b/include/WTL/Samples/BmpView/BmpView.vcxproj.user
new file mode 100644 (file)
index 0000000..ace9a86
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/BmpView/list.h b/include/WTL/Samples/BmpView/list.h
new file mode 100644 (file)
index 0000000..339f939
--- /dev/null
@@ -0,0 +1,125 @@
+// list.h : interface of the CMruList class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+
+class CMruList : public CWindowImpl<CMruList, CListBox>
+{
+public:
+       SIZE m_size;
+
+
+       CMruList()
+       {
+               m_size.cx = 200;
+               m_size.cy = 150;
+       }
+
+       HWND Create(HWND hWndParent)
+       {
+               CWindowImpl<CMruList, CListBox>::Create(hWndParent, rcDefault, NULL,
+                       WS_POPUP | WS_THICKFRAME | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VSCROLL | LBS_NOINTEGRALHEIGHT,
+                       WS_EX_CLIENTEDGE);
+               if(IsWindow())
+                       SetFont(AtlGetStockFont(DEFAULT_GUI_FONT));
+               return m_hWnd;
+       }
+
+       BOOL BuildList(CRecentDocumentList& mru)
+       {
+               ATLASSERT(IsWindow());
+
+               ResetContent();
+
+               int nSize = mru.m_arrDocs.GetSize();
+               for(int i = 0; i < nSize; i++)
+                       InsertString(0, mru.m_arrDocs[i].szDocName);    // docs are in reversed order in the array
+
+               if(nSize > 0)
+               {
+                       SetCurSel(0);
+                       SetTopIndex(0);
+               }
+
+               return TRUE;
+       }
+
+       BOOL ShowList(int x, int y)
+       {
+               return SetWindowPos(NULL, x, y, m_size.cx, m_size.cy, SWP_NOZORDER | SWP_SHOWWINDOW);
+       }
+
+       void HideList()
+       {
+               RECT rect;
+               GetWindowRect(&rect);
+               m_size.cx = rect.right - rect.left;
+               m_size.cy = rect.bottom - rect.top;
+               ShowWindow(SW_HIDE);
+       }
+
+       void FireCommand()
+       {
+               int nSel = GetCurSel();
+               if(nSel != LB_ERR)
+               {
+                       ::SetFocus(GetParent());        // will hide this window
+                       ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM((WORD)(ID_FILE_MRU_FIRST + nSel), LBN_DBLCLK), (LPARAM)m_hWnd);
+               }
+       }
+
+       BEGIN_MSG_MAP(CMruList)
+               MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
+               MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)
+               MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
+               MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
+       END_MSG_MAP()
+
+       LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(wParam == VK_RETURN)
+                       FireCommand();
+               else
+                       bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnLButtonDblClk(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               FireCommand();
+               return 0;
+       }
+
+       LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               HideList();
+               return 0;
+       }
+
+       LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               switch(lRet)
+               {
+               case HTLEFT:
+               case HTTOP:
+               case HTTOPLEFT:
+               case HTTOPRIGHT:
+               case HTBOTTOMLEFT:
+                       lRet = HTCLIENT;        // don't allow resizing here
+                       break;
+               default:
+                       break;
+               }
+               return lRet;
+       }
+};
+
+#endif // __LIST_H__
diff --git a/include/WTL/Samples/BmpView/mainfrm.h b/include/WTL/Samples/BmpView/mainfrm.h
new file mode 100644 (file)
index 0000000..762fbde
--- /dev/null
@@ -0,0 +1,608 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __MAINFRM_H__
+#define __MAINFRM_H__
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#define FILE_MENU_POSITION     0
+#define RECENT_MENU_POSITION   6
+#define POPUP_MENU_POSITION    0
+
+LPCTSTR g_lpcstrMRURegKey = _T("Software\\Microsoft\\WTL Samples\\BmpView");
+LPCTSTR g_lpcstrApp = _T("BmpView");
+
+
+class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>,
+               public CMessageFilter, public CIdleHandler
+#ifndef _WIN32_WCE
+               , public CPrintJobInfo
+#endif // _WIN32_WCE
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
+
+#ifndef _WIN32_WCE
+       CCommandBarCtrl m_CmdBar;
+       CRecentDocumentList m_mru;
+       CMruList m_list;
+#endif // _WIN32_WCE
+       CBitmapView m_view;
+
+       TCHAR m_szFilePath[MAX_PATH];
+
+       // printing support
+#ifndef _WIN32_WCE
+       CPrinter m_printer;
+       CDevMode m_devmode;
+       CPrintPreviewWindow m_wndPreview;
+       CEnhMetaFile m_enhmetafile;
+       RECT m_rcMargin;
+       bool m_bPrintPreview;
+#endif // _WIN32_WCE
+
+
+       CMainFrame() 
+#ifndef _WIN32_WCE
+               : m_bPrintPreview(false)
+#endif // _WIN32_WCE
+       {
+#ifndef _WIN32_WCE
+               ::SetRect(&m_rcMargin, 1000, 1000, 1000, 1000);
+               m_printer.OpenDefaultPrinter();
+               m_devmode.CopyFromPrinter(m_printer);
+#endif // _WIN32_WCE
+               m_szFilePath[0] = 0;
+       }
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+       }
+
+       virtual BOOL OnIdle()
+       {
+               BOOL bEnable = !m_view.m_bmp.IsNull();
+#ifndef _WIN32_WCE
+               UIEnable(ID_FILE_PRINT, bEnable);
+               UIEnable(ID_FILE_PRINT_PREVIEW, bEnable);
+               UISetCheck(ID_FILE_PRINT_PREVIEW, m_bPrintPreview);
+#endif // _WIN32_WCE
+               UIEnable(ID_EDIT_COPY, bEnable);
+               UIEnable(ID_EDIT_PASTE, ::IsClipboardFormatAvailable(CF_BITMAP));
+               UIEnable(ID_EDIT_CLEAR, bEnable);
+               UIEnable(ID_VIEW_PROPERTIES, bEnable);
+#ifndef _WIN32_WCE
+               UISetCheck(ID_RECENT_BTN, m_list.IsWindowVisible());
+#endif // _WIN32_WCE
+#ifndef WIN32_PLATFORM_PSPC
+               UIUpdateToolBar();
+#endif // WIN32_PLATFORM_PSPC
+
+               return FALSE;
+       }
+
+#ifndef _WIN32_WCE
+       void TogglePrintPreview()
+       {
+               if(m_bPrintPreview)     // close it
+               {
+                       ATLASSERT(m_hWndClient == m_wndPreview.m_hWnd);
+
+                       m_hWndClient = m_view;
+                       m_view.ShowWindow(SW_SHOW);
+                       m_wndPreview.DestroyWindow();
+               }
+               else                    // display it
+               {
+                       ATLASSERT(m_hWndClient == m_view.m_hWnd);
+
+                       m_wndPreview.SetPrintPreviewInfo(m_printer, m_devmode.m_pDevMode, this, 0, 0);
+                       m_wndPreview.SetPage(0);
+
+                       m_wndPreview.Create(m_hWnd, rcDefault, NULL, 0, WS_EX_CLIENTEDGE);
+                       m_view.ShowWindow(SW_HIDE);
+                       m_hWndClient = m_wndPreview;
+               }
+
+               m_bPrintPreview = !m_bPrintPreview;
+               UpdateLayout();
+       }
+#endif // _WIN32_WCE
+
+#ifndef WIN32_PLATFORM_PSPC
+       void UpdateTitleBar(LPCTSTR lpstrTitle)
+       {
+               CString strDefault;
+               strDefault.LoadString(IDR_MAINFRAME);
+               CString strTitle = strDefault;
+               if(lpstrTitle != NULL)
+               {
+                       strTitle = lpstrTitle;
+                       strTitle += _T(" - ");
+                       strTitle += strDefault;
+               }
+               SetWindowText(strTitle);
+       }
+#endif // WIN32_PLATFORM_PSPC
+
+#ifndef _WIN32_WCE
+       //print job info callbacks
+       virtual bool IsValidPage(UINT nPage)
+       {
+               return (nPage == 0);    // we have only one page
+       }
+
+       virtual bool PrintPage(UINT nPage, HDC hDC)
+       {
+               if (nPage >= 1)         // we have only one page
+                       return false;
+
+               ATLASSERT(!m_view.m_bmp.IsNull());
+
+               RECT rcPage = 
+                       { 0, 0, 
+                       ::GetDeviceCaps(hDC, PHYSICALWIDTH) - 2 * ::GetDeviceCaps(hDC, PHYSICALOFFSETX),
+                       ::GetDeviceCaps(hDC, PHYSICALHEIGHT) - 2 * ::GetDeviceCaps(hDC, PHYSICALOFFSETY) };
+
+               CDCHandle dc = hDC;
+               CClientDC dcScreen(m_hWnd);
+               CDC dcMem;
+               dcMem.CreateCompatibleDC(dcScreen);
+               HBITMAP hBmpOld = dcMem.SelectBitmap(m_view.m_bmp);
+               int cx = m_view.m_size.cx;
+               int cy = m_view.m_size.cy;
+
+               // calc scaling factor, so that bitmap is not too small
+               // (based on the width only, max 3/4 width)
+               int nScale = ::MulDiv(rcPage.right, 3, 4) / cx;
+               if(nScale == 0)         // too big already
+                       nScale = 1;
+               // calc margines to center bitmap
+               int xOff = (rcPage.right - nScale * cx) / 2;
+               if(xOff < 0)
+                       xOff = 0;
+               int yOff = (rcPage.bottom - nScale * cy) / 2;
+               if(yOff < 0)
+                       yOff = 0;
+               // ensure that preview doesn't go outside of the page
+               int cxBlt = nScale * cx;
+               if(xOff + cxBlt > rcPage.right)
+                       cxBlt = rcPage.right - xOff;
+               int cyBlt = nScale * cy;
+               if(yOff + cyBlt > rcPage.bottom)
+                       cyBlt = rcPage.bottom - yOff;
+
+               // now paint bitmap
+               dc.StretchBlt(xOff, yOff, cxBlt, cyBlt, dcMem, 0, 0, cx, cy, SRCCOPY);
+
+               dcMem.SelectBitmap(hBmpOld);
+
+               return true;
+       }
+#endif // _WIN32_WCE
+
+       BEGIN_MSG_MAP_EX(CMainFrame)
+               MSG_WM_CREATE(OnCreate)
+#ifndef _WIN32_WCE
+               MSG_WM_CONTEXTMENU(OnContextMenu)
+#endif // _WIN32_WCE
+
+               COMMAND_ID_HANDLER_EX(ID_FILE_OPEN, OnFileOpen)
+#ifndef _WIN32_WCE
+               COMMAND_RANGE_HANDLER_EX(ID_FILE_MRU_FIRST, ID_FILE_MRU_LAST, OnFileRecent)
+               COMMAND_ID_HANDLER_EX(ID_RECENT_BTN, OnRecentButton)
+#endif // _WIN32_WCE
+#ifndef _WIN32_WCE
+               COMMAND_ID_HANDLER_EX(ID_FILE_PRINT, OnFilePrint);
+               COMMAND_ID_HANDLER_EX(ID_FILE_PAGE_SETUP, OnFilePageSetup)
+               COMMAND_ID_HANDLER_EX(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview);
+#endif // _WIN32_WCE
+               COMMAND_ID_HANDLER_EX(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER_EX(ID_EDIT_COPY, OnEditCopy)
+               COMMAND_ID_HANDLER_EX(ID_EDIT_PASTE, OnEditPaste)
+               COMMAND_ID_HANDLER_EX(ID_EDIT_CLEAR, OnEditClear)
+#ifndef _WIN32_WCE
+               COMMAND_ID_HANDLER_EX(ID_VIEW_TOOLBAR, OnViewToolBar)
+#endif // _WIN32_WCE
+#ifndef WIN32_PLATFORM_PSPC
+               COMMAND_ID_HANDLER_EX(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+#endif // WIN32_PLATFORM_PSPC
+               COMMAND_ID_HANDLER_EX(ID_VIEW_PROPERTIES, OnViewProperties)
+               COMMAND_ID_HANDLER_EX(ID_APP_ABOUT, OnAppAbout)
+
+               CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
+               CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
+       END_MSG_MAP()
+
+       BEGIN_UPDATE_UI_MAP(CMainFrame)
+#ifndef _WIN32_WCE
+               UPDATE_ELEMENT(ID_FILE_PRINT, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_FILE_PRINT_PREVIEW, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+#endif // _WIN32_WCE
+               UPDATE_ELEMENT(ID_EDIT_COPY, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_PASTE, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_CLEAR, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+#ifndef _WIN32_WCE
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+#endif // _WIN32_WCE
+#ifndef WIN32_PLATFORM_PSPC
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+#endif // WIN32_PLATFORM_PSPC
+               UPDATE_ELEMENT(ID_VIEW_PROPERTIES, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_RECENT_BTN, UPDUI_TOOLBAR)
+       END_UPDATE_UI_MAP()
+
+       int OnCreate(LPCREATESTRUCT /*lpCreateStruct*/)
+       {
+#ifndef _WIN32_WCE
+               // create command bar window
+               HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+               // atach menu
+               m_CmdBar.AttachMenu(GetMenu());
+               // load command bar images
+               m_CmdBar.LoadImages(IDR_MAINFRAME);
+               // remove old menu
+               SetMenu(NULL);
+
+               // create toolbar and rebar
+               HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+               CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+               AddSimpleReBarBand(hWndCmdBar);
+               AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+#else // _WIN32_WCE
+#ifndef WIN32_PLATFORM_PSPC
+               CreateSimpleCECommandBar(MAKEINTRESOURCE(IDR_MAINFRAME));
+               CreateSimpleToolBar();
+#else // WIN32_PLATFORM_PSPC
+               CreateSimpleCEMenuBar(IDR_MAINFRAME, SHCMBF_HMENU);
+#endif // WIN32_PLATFORM_PSPC
+#endif // _WIN32_WCE
+
+#ifndef WIN32_PLATFORM_PSPC
+               // create status bar
+               CreateSimpleStatusBar();
+#endif // WIN32_PLATFORM_PSPC
+
+               // create view window
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+               m_view.SetBitmap(NULL);
+
+#ifndef _WIN32_WCE
+               // set up MRU stuff
+               CMenuHandle menu = m_CmdBar.GetMenu();
+               CMenuHandle menuFile = menu.GetSubMenu(FILE_MENU_POSITION);
+               CMenuHandle menuMru = menuFile.GetSubMenu(RECENT_MENU_POSITION);
+               m_mru.SetMenuHandle(menuMru);
+               m_mru.SetMaxEntries(12);
+
+               m_mru.ReadFromRegistry(g_lpcstrMRURegKey);
+
+               // create MRU list
+               m_list.Create(m_hWnd);
+#endif // _WIN32_WCE
+
+#ifndef WIN32_PLATFORM_PSPC
+               // set up update UI
+#ifndef _WIN32_WCE
+               UIAddToolBar(hWndToolBar);
+#else // _WIN32_WCE
+               UIAddToolBar(m_hWndToolBar);
+#endif // _WIN32_WCE
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+#endif // WIN32_PLATFORM_PSPC
+
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               return 0;
+       }
+
+#ifndef _WIN32_WCE
+       void OnContextMenu(CWindow wnd, CPoint point)
+       {
+               if(wnd.m_hWnd == m_view.m_hWnd)
+               {
+                       CMenu menu;
+                       menu.LoadMenu(IDR_CONTEXTMENU);
+                       CMenuHandle menuPopup = menu.GetSubMenu(POPUP_MENU_POSITION);
+                       m_CmdBar.TrackPopupMenu(menuPopup, TPM_RIGHTBUTTON | TPM_VERTICAL, point.x, point.y);
+               }
+               else
+               {
+                       SetMsgHandled(FALSE);
+               }
+       }
+#endif // _WIN32_WCE
+
+       void OnFileExit(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               PostMessage(WM_CLOSE);
+       }
+
+       void OnFileOpen(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               CFileDialog dlg(TRUE, _T("bmp"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("Bitmap Files (*.bmp)\0*.bmp\0All Files (*.*)\0*.*\0"), m_hWnd);
+               if(dlg.DoModal() == IDOK)
+               {
+#ifndef _WIN32_WCE
+                       if(m_bPrintPreview)
+                               TogglePrintPreview();
+
+                       HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, dlg.m_szFileName, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_LOADFROMFILE);
+#else
+                       // Using alternate image load routines here since LR_LOADFROMFILE isn't supported.
+#ifdef WIN32_PLATFORM_PSPC
+                       HBITMAP hBmp = (HBITMAP)::SHLoadImageFile(dlg.m_szFileName);
+#else  // SHLoadDIBitmap (below) is for CE, but only loads .bmp; SHLoadImageFile (above) loads .bmp, .gif, .jpg, .png
+                       HBITMAP hBmp = (HBITMAP)::SHLoadDIBitmap(dlg.m_szFileName);
+#endif // WIN32_PLATFORM_PSPC
+#endif // _WIN32_WCE
+                       if(hBmp != NULL)
+                       {
+                               m_view.SetBitmap(hBmp);
+#ifndef _WIN32_WCE
+                               m_mru.AddToList(dlg.m_ofn.lpstrFile);
+                               m_mru.WriteToRegistry(g_lpcstrMRURegKey);
+#endif // _WIN32_WCE
+#ifndef WIN32_PLATFORM_PSPC
+                               UpdateTitleBar(dlg.m_szFileTitle);
+#endif // WIN32_PLATFORM_PSPC
+                               lstrcpy(m_szFilePath, dlg.m_szFileName);
+                       }
+                       else
+                       {
+                               CString strMsg = _T("Can't load image from:\n");
+                               strMsg += dlg.m_szFileName;
+                               MessageBox(strMsg, g_lpcstrApp, MB_OK | MB_ICONERROR);
+                       }
+               }
+       }
+
+#ifndef _WIN32_WCE
+       void OnFileRecent(UINT /*uNotifyCode*/, int nID, CWindow /*wnd*/)
+       {
+               if(m_bPrintPreview)
+                       TogglePrintPreview();
+
+               // get file name from the MRU list
+               TCHAR szFile[MAX_PATH];
+               if(m_mru.GetFromList(nID, szFile, MAX_PATH))
+               {
+                       // open file
+                       HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, szFile, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_LOADFROMFILE);
+                       if(hBmp != NULL)
+                       {
+                               m_view.SetBitmap(hBmp);
+                               m_mru.MoveToTop(nID);
+                               // get file name without the path
+                               int nFileNamePos = 0;
+                               for(int i = lstrlen(szFile) - 1; i >= 0; i--)
+                               {
+                                       if(szFile[i] == _T('\\'))
+                                       {
+                                               nFileNamePos = i + 1;
+                                               break;
+                                       }
+                               }
+                               UpdateTitleBar(&szFile[nFileNamePos]);
+                               lstrcpy(m_szFilePath, szFile);
+                       }
+                       else
+                       {
+                               m_mru.RemoveFromList(nID);
+                       }
+                       m_mru.WriteToRegistry(g_lpcstrMRURegKey);
+               }
+               else
+               {
+                       ::MessageBeep(MB_ICONERROR);
+               }
+       }
+
+       void OnRecentButton(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               UINT uBandID = ATL_IDW_BAND_FIRST + 1;  // toolbar is second added band
+               CReBarCtrl rebar = m_hWndToolBar;
+               int nBandIndex = rebar.IdToIndex(uBandID);
+               REBARBANDINFO rbbi = { 0 };
+               rbbi.cbSize = RunTimeHelper::SizeOf_REBARBANDINFO();
+               rbbi.fMask = RBBIM_CHILD;
+               rebar.GetBandInfo(nBandIndex, &rbbi);
+               CToolBarCtrl wndToolBar = rbbi.hwndChild;
+
+               int nIndex = wndToolBar.CommandToIndex(ID_RECENT_BTN);
+               CRect rect;
+               wndToolBar.GetItemRect(nIndex, rect);
+               wndToolBar.ClientToScreen(rect);
+
+               // build and display MRU list in a popup
+               m_list.BuildList(m_mru);
+               m_list.ShowList(rect.left, rect.bottom);
+       }
+#endif // _WIN32_WCE
+
+#ifndef _WIN32_WCE
+       void OnFilePrint(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               CPrintDialog dlg(FALSE);
+               dlg.m_pd.hDevMode = m_devmode.CopyToHDEVMODE();
+               dlg.m_pd.hDevNames = m_printer.CopyToHDEVNAMES();
+               dlg.m_pd.nMinPage = 1;
+               dlg.m_pd.nMaxPage = 1;
+
+               if(dlg.DoModal() == IDOK)
+               {
+                       m_devmode.CopyFromHDEVMODE(dlg.m_pd.hDevMode);
+                       m_printer.ClosePrinter();
+                       m_printer.OpenPrinter(dlg.m_pd.hDevNames, m_devmode.m_pDevMode);
+
+                       CPrintJob job;
+                       job.StartPrintJob(false, m_printer, m_devmode.m_pDevMode, this, _T("BmpView Document"), 0, 0, (dlg.PrintToFile() != FALSE));
+               }
+
+               ::GlobalFree(dlg.m_pd.hDevMode);
+               ::GlobalFree(dlg.m_pd.hDevNames);
+       }
+
+       void OnFilePageSetup(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               CPageSetupDialog dlg;
+               dlg.m_psd.hDevMode = m_devmode.CopyToHDEVMODE();
+               dlg.m_psd.hDevNames = m_printer.CopyToHDEVNAMES();
+               dlg.m_psd.rtMargin = m_rcMargin;
+
+               if(dlg.DoModal() == IDOK)
+               {
+                       if(m_bPrintPreview)
+                               TogglePrintPreview();
+
+                       m_devmode.CopyFromHDEVMODE(dlg.m_psd.hDevMode);
+                       m_printer.ClosePrinter();
+                       m_printer.OpenPrinter(dlg.m_psd.hDevNames, m_devmode.m_pDevMode);
+                       m_rcMargin = dlg.m_psd.rtMargin;
+               }
+
+               ::GlobalFree(dlg.m_psd.hDevMode);
+               ::GlobalFree(dlg.m_psd.hDevNames);
+       }
+
+       void OnFilePrintPreview(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               TogglePrintPreview();
+       }
+#endif // _WIN32_WCE
+
+       void OnEditCopy(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               if(::OpenClipboard(NULL))
+               {
+#ifndef _WIN32_WCE
+                       HBITMAP hBitmapCopy = (HBITMAP)::CopyImage(m_view.m_bmp.m_hBitmap, IMAGE_BITMAP, 0, 0, 0);
+#else // _WIN32_WCE
+                       // TODO - JoshHe 7/03/2003 - provide alternate BitMap copy routine.
+                       HBITMAP hBitmapCopy = NULL;
+#endif // _WIN32_WCE
+                       if(hBitmapCopy != NULL)
+                               ::SetClipboardData(CF_BITMAP, hBitmapCopy);
+                       else
+                               MessageBox(_T("Can't copy bitmap"), g_lpcstrApp, MB_OK | MB_ICONERROR);
+
+                       ::CloseClipboard();
+               }
+               else
+               {
+                       MessageBox(_T("Can't open clipboard to copy"), g_lpcstrApp, MB_OK | MB_ICONERROR);
+               }
+       }
+
+       void OnEditPaste(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+#ifndef _WIN32_WCE
+               if(m_bPrintPreview)
+                       TogglePrintPreview();
+#endif // _WIN32_WCE
+
+               if(::OpenClipboard(NULL))
+               {
+                       HBITMAP hBitmap = (HBITMAP)::GetClipboardData(CF_BITMAP);
+                       ::CloseClipboard();
+                       if(hBitmap != NULL)
+                       {
+#ifndef _WIN32_WCE
+                               HBITMAP hBitmapCopy = (HBITMAP)::CopyImage(hBitmap, IMAGE_BITMAP, 0, 0, 0);
+#else // _WIN32_WCE
+                               // TODO - JoshHe 7/03/2003 - provide alternate BitMap copy routine.
+                               HBITMAP hBitmapCopy = NULL;
+#endif // _WIN32_WCE
+                               if(hBitmapCopy != NULL)
+                               {
+                                       m_view.SetBitmap(hBitmapCopy);
+#ifndef WIN32_PLATFORM_PSPC
+                                       UpdateTitleBar(_T("(Clipboard)"));
+#endif // WIN32_PLATFORM_PSPC
+                                       m_szFilePath[0] = 0;
+                               }
+                               else
+                               {
+                                       MessageBox(_T("Can't paste bitmap"), g_lpcstrApp, MB_OK | MB_ICONERROR);
+                               }
+                       }
+                       else
+                       {
+                               MessageBox(_T("Can't open bitmap from the clipboard"), g_lpcstrApp, MB_OK | MB_ICONERROR);
+                       }
+               }
+               else
+               {
+                       MessageBox(_T("Can't open clipboard to paste"), g_lpcstrApp, MB_OK | MB_ICONERROR);
+               }
+       }
+
+       void OnEditClear(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+#ifndef _WIN32_WCE
+               if(m_bPrintPreview)
+                       TogglePrintPreview();
+#endif // _WIN32_WCE
+
+               m_view.SetBitmap(NULL);
+#ifndef WIN32_PLATFORM_PSPC
+               UpdateTitleBar(NULL);
+#endif // WIN32_PLATFORM_PSPC
+               m_szFilePath[0] = 0;
+       }
+
+#ifndef _WIN32_WCE
+       void OnViewToolBar(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               static BOOL bNew = TRUE;        // initially visible
+               bNew = !bNew;
+               UINT uBandID = ATL_IDW_BAND_FIRST + 1;  // toolbar is second added band
+               CReBarCtrl rebar = m_hWndToolBar;
+               int nBandIndex = rebar.IdToIndex(uBandID);
+               rebar.ShowBand(nBandIndex, bNew);
+               UISetCheck(ID_VIEW_TOOLBAR, bNew);
+               UpdateLayout();
+       }
+#endif // _WIN32_WCE
+
+#ifndef WIN32_PLATFORM_PSPC
+       void OnViewStatusBar(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               BOOL bNew = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bNew ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bNew);
+               UpdateLayout();
+       }
+#endif // WIN32_PLATFORM_PSPC
+
+       void OnViewProperties(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               CBmpProperties prop;
+               if(lstrlen(m_szFilePath) > 0)   // we have a file name
+                       prop.SetFileInfo(m_szFilePath, NULL);
+               else                            // must be clipboard then
+                       prop.SetFileInfo(NULL, m_view.m_bmp.m_hBitmap);
+               prop.DoModal();
+       }
+
+       void OnAppAbout(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wnd*/)
+       {
+               CSimpleDialog<IDD_ABOUTBOX> dlg;
+               dlg.DoModal();
+       }
+};
+
+#endif // __MAINFRM_H__
diff --git a/include/WTL/Samples/BmpView/props.h b/include/WTL/Samples/BmpView/props.h
new file mode 100644 (file)
index 0000000..ab3d6a1
--- /dev/null
@@ -0,0 +1,345 @@
+// props.h : interface for the properties classes
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __PROPS_H__
+#define __PROPS_H__
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+// not defined in original the VC6 headers
+#ifndef BI_JPEG
+#define BI_JPEG       4L
+#endif
+#ifndef BI_PNG
+#define BI_PNG        5L
+#endif
+
+class CFileName : public CWindowImpl<CFileName>
+{
+public:
+       DECLARE_WND_CLASS_EX(NULL, 0, COLOR_3DFACE)
+
+       LPCTSTR m_lpstrFilePath;
+
+#ifndef _WIN32_WCE
+       enum { m_nToolTipID = 1313 };
+       CToolTipCtrl m_tooltip;
+#endif // _WIN32_WCE
+
+
+       CFileName() : m_lpstrFilePath(NULL)
+       { }
+
+       void Init(HWND hWnd, LPCTSTR lpstrName)
+       {
+               ATLASSERT(::IsWindow(hWnd));
+               SubclassWindow(hWnd);
+
+#ifndef _WIN32_WCE
+               // Set tooltip
+               m_tooltip.Create(m_hWnd);
+               ATLASSERT(m_tooltip.IsWindow());
+               RECT rect;
+               GetClientRect(&rect);
+               CToolInfo ti(0, m_hWnd, m_nToolTipID, &rect, NULL);
+               m_tooltip.AddTool(&ti);
+
+               // set text
+               m_lpstrFilePath = lpstrName;
+               if(m_lpstrFilePath == NULL)
+                       return;
+
+               CClientDC dc(m_hWnd);   // will not really paint
+               HFONT hFontOld = dc.SelectFont(AtlGetDefaultGuiFont());
+
+               RECT rcText = rect;
+               dc.DrawText(m_lpstrFilePath, -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_CALCRECT);
+               BOOL bTooLong = (rcText.right > rect.right);
+               if(bTooLong)
+                       m_tooltip.UpdateTipText(m_lpstrFilePath, m_hWnd, m_nToolTipID);
+               m_tooltip.Activate(bTooLong);
+
+               dc.SelectFont(hFontOld);
+#endif // _WIN32_WCE
+
+               Invalidate();
+               UpdateWindow();
+       }
+
+       BEGIN_MSG_MAP(CFileName)
+#ifndef _WIN32_WCE
+               MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
+#endif // _WIN32_WCE
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+       END_MSG_MAP()
+
+#ifndef _WIN32_WCE
+       LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if(m_tooltip.IsWindow())
+               {
+                       MSG msg = { m_hWnd, uMsg, wParam, lParam };
+                       m_tooltip.RelayEvent(&msg);
+               }
+               bHandled = FALSE;
+               return 1;
+       }
+#endif // _WIN32_WCE
+
+       LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CPaintDC dc(m_hWnd);
+               if(m_lpstrFilePath != NULL)
+               {
+                       RECT rect;
+                       GetClientRect(&rect);
+
+                       dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
+                       dc.SetBkMode(TRANSPARENT);
+                       HFONT hFontOld = dc.SelectFont(AtlGetDefaultGuiFont());
+
+#ifndef _WIN32_WCE
+                       dc.DrawText(m_lpstrFilePath, -1, &rect, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_PATH_ELLIPSIS);
+#else // _WIN32_WCE
+                       dc.DrawText(m_lpstrFilePath, -1, &rect, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_NOPREFIX);
+#endif // _WIN32_WCE
+
+                       dc.SelectFont(hFontOld);
+               }
+               return 0;
+       }
+};
+
+class CPageOne : public CPropertyPageImpl<CPageOne>
+{
+public:
+       enum { IDD = IDD_PROP_PAGE1 };
+
+       LPCTSTR m_lpstrFilePath;
+       CFileName m_filename;
+
+
+       CPageOne() : m_lpstrFilePath(NULL)
+       { }
+
+       BEGIN_MSG_MAP(CPageOne)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               CHAIN_MSG_MAP(CPropertyPageImpl<CPageOne>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               if(m_lpstrFilePath != NULL)     // get and set file properties
+               {
+                       m_filename.Init(GetDlgItem(IDC_FILELOCATION), m_lpstrFilePath);
+
+                       WIN32_FIND_DATA fd;
+                       HANDLE hFind = ::FindFirstFile(m_lpstrFilePath, &fd);
+                       if(hFind != INVALID_HANDLE_VALUE)
+                       {
+                               int nSizeK = (int)(fd.nFileSizeLow / 1024);     // assume it not bigger than 2GB
+                               if(nSizeK == 0 && fd.nFileSizeLow != 0)
+                                       nSizeK = 1;
+                               TCHAR szBuff[100];
+                               wsprintf(szBuff, _T("%i KB"), nSizeK);
+                               SetDlgItemText(IDC_FILESIZE, szBuff);
+                               SYSTEMTIME st;
+                               ::FileTimeToSystemTime(&fd.ftCreationTime, &st);
+                               ::GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, _T("dddd, MMMM dd',' yyyy',' "), szBuff, sizeof(szBuff) / sizeof(szBuff[0]));
+                               TCHAR szBuff1[50];
+                               ::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, _T("hh':'mm':'ss tt"), szBuff1, sizeof(szBuff1) / sizeof(szBuff1[0]));
+                               lstrcat(szBuff, szBuff1);
+                               SetDlgItemText(IDC_FILEDATE, szBuff);
+
+                               szBuff[0] = 0;
+                               if((fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) != 0)
+                                       lstrcat(szBuff, _T("Archive, "));
+                               if((fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0)
+                                       lstrcat(szBuff, _T("Read-only, "));
+                               if((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0)
+                                       lstrcat(szBuff, _T("Hidden, "));
+                               if((fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0)
+                                       lstrcat(szBuff, _T("System"));
+                               int nLen = lstrlen(szBuff);
+                               if(nLen >= 2 && szBuff[nLen - 2] == _T(','))
+                                       szBuff[nLen - 2] = 0;
+                               SetDlgItemText(IDC_FILEATTRIB, szBuff);
+
+                               ::FindClose(hFind);
+                       }
+               }
+               else
+               {
+                       SetDlgItemText(IDC_FILELOCATION, _T("(Clipboard)"));
+                       SetDlgItemText(IDC_FILESIZE, _T("N/A"));
+                       SetDlgItemText(IDC_FILEDATE, _T("N/A"));
+                       SetDlgItemText(IDC_FILEATTRIB, _T("N/A"));
+               }
+
+               return TRUE;
+       }
+};
+
+class CPageTwo : public CPropertyPageImpl<CPageTwo>
+{
+public:
+       enum { IDD = IDD_PROP_PAGE2 };
+
+       LPCTSTR m_lpstrFilePath;
+       CBitmapHandle m_bmp;
+
+
+       CPageTwo() : m_lpstrFilePath(NULL)
+       { }
+
+       BEGIN_MSG_MAP(CPageTwo)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               CHAIN_MSG_MAP(CPropertyPageImpl<CPageTwo>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // Special - remove unused buttons, move Close button, center wizard
+               CPropertySheetWindow sheet = GetPropertySheet();
+#if !defined(_AYGSHELL_H_) && !defined(__AYGSHELL_H__) // PPC specific
+               sheet.CancelToClose();
+               RECT rect;
+               CButton btnCancel = sheet.GetDlgItem(IDCANCEL);
+               btnCancel.GetWindowRect(&rect);
+               sheet.ScreenToClient(&rect);
+               btnCancel.ShowWindow(SW_HIDE);
+               CButton btnClose = sheet.GetDlgItem(IDOK);
+               btnClose.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOSIZE);
+               sheet.CenterWindow(GetPropertySheet().GetParent());
+
+               sheet.ModifyStyleEx(WS_EX_CONTEXTHELP, 0);
+#endif // (_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
+
+               // get and display bitmap prperties
+               SetDlgItemText(IDC_TYPE, _T("Windows 3.x Bitmap (BMP)"));
+               LPTSTR lpstrCompression = _T("Uncompressed");;
+
+               if(m_lpstrFilePath != NULL)
+               {
+#ifndef _WIN32_WCE 
+                       HANDLE hFile = ::CreateFile(m_lpstrFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+#else
+                       HANDLE hFile = ::CreateFile(m_lpstrFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif // _WIN32_WCE
+                       ATLASSERT(hFile != INVALID_HANDLE_VALUE);
+                       if(hFile != INVALID_HANDLE_VALUE)
+                       {
+                               DWORD dwRead = 0;
+                               BITMAPFILEHEADER bfh;
+                               ::ReadFile(hFile, &bfh, sizeof(bfh), &dwRead, NULL);
+                               BITMAPINFOHEADER bih;
+                               ::ReadFile(hFile, &bih, sizeof(bih), &dwRead, NULL);
+                               ::CloseHandle(hFile);
+
+                               SetDlgItemInt(IDC_WIDTH, bih.biWidth);
+                               SetDlgItemInt(IDC_HEIGHT, bih.biHeight);
+                               SetDlgItemInt(IDC_HORRES, ::MulDiv(bih.biXPelsPerMeter, 254, 10000));
+                               SetDlgItemInt(IDC_VERTRES, ::MulDiv(bih.biYPelsPerMeter, 254, 10000));
+                               SetDlgItemInt(IDC_BITDEPTH, bih.biBitCount);
+
+                               switch(bih.biCompression)
+                               {
+#ifndef _WIN32_WCE
+                               case BI_RLE4:
+                               case BI_RLE8:
+                                       lpstrCompression = _T("RLE");
+                                       break;
+#endif // _WIN32_WCE
+                               case BI_BITFIELDS:
+                                       lpstrCompression = _T("Uncompressed with bitfields");
+                                       break;
+                               case BI_JPEG:
+                               case BI_PNG:
+                                       lpstrCompression = _T("Unknown");
+                                       break;
+                               }
+                               SetDlgItemText(IDC_COMPRESSION, lpstrCompression);
+                       }
+               }
+               else            // must be pasted from the clipboard
+               {
+                       ATLASSERT(!m_bmp.IsNull());
+                       BITMAP bitmap = { 0 };
+                       bool bRet = m_bmp.GetBitmap(bitmap);
+                       ATLASSERT(bRet);
+                       if(bRet)
+                       {
+                               CClientDC dc(NULL);
+                               SetDlgItemInt(IDC_WIDTH, bitmap.bmWidth);
+                               SetDlgItemInt(IDC_HEIGHT, bitmap.bmHeight);
+                               // should we use screen resolution here???
+                               SetDlgItemInt(IDC_HORRES, dc.GetDeviceCaps(LOGPIXELSX));
+                               SetDlgItemInt(IDC_VERTRES, dc.GetDeviceCaps(LOGPIXELSX));
+                               SetDlgItemInt(IDC_BITDEPTH, bitmap.bmBitsPixel);
+                               SetDlgItemText(IDC_COMPRESSION, lpstrCompression);
+                       }
+               }
+
+               return TRUE;
+       }
+};
+
+class CPageThree : public CPropertyPageImpl<CPageThree>
+{
+public:
+       enum { IDD = IDD_PROP_PAGE3 };
+
+       BEGIN_MSG_MAP(CPageThree)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               CHAIN_MSG_MAP(CPropertyPageImpl<CPageThree>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // get and set screen properties
+               CClientDC dc(NULL);
+               SetDlgItemInt(IDC_WIDTH, dc.GetDeviceCaps(HORZRES));
+               SetDlgItemInt(IDC_HEIGHT, dc.GetDeviceCaps(VERTRES));
+               SetDlgItemInt(IDC_HORRES, dc.GetDeviceCaps(LOGPIXELSX));
+               SetDlgItemInt(IDC_VERTRES, dc.GetDeviceCaps(LOGPIXELSY));
+               SetDlgItemInt(IDC_BITDEPTH, dc.GetDeviceCaps(BITSPIXEL));
+
+               return TRUE;
+       }
+};
+
+class CBmpProperties : public CPropertySheetImpl<CBmpProperties>
+{
+public:
+       CPageOne m_page1;
+       CPageTwo m_page2;
+       CPageThree m_page3;
+
+
+       CBmpProperties()
+       {
+               m_psh.dwFlags |= PSH_NOAPPLYNOW;
+
+               AddPage(m_page1);
+               AddPage(m_page2);
+               AddPage(m_page3);
+               SetActivePage(1);
+               SetTitle(_T("Bitmap Properties"));
+       }
+
+       void SetFileInfo(LPCTSTR lpstrFilePath, HBITMAP hBitmap)
+       {
+               m_page1.m_lpstrFilePath = lpstrFilePath;
+               m_page2.m_lpstrFilePath = lpstrFilePath;
+               m_page2.m_bmp = hBitmap;
+       }
+
+       BEGIN_MSG_MAP(CBmpProperties)
+               CHAIN_MSG_MAP(CPropertySheetImpl<CBmpProperties>)
+       END_MSG_MAP()
+};
+
+#endif // __PROPS_H__
diff --git a/include/WTL/Samples/BmpView/res/BmpView.ico b/include/WTL/Samples/BmpView/res/BmpView.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/Samples/BmpView/res/BmpView.ico differ
diff --git a/include/WTL/Samples/BmpView/res/Toolbar.bmp b/include/WTL/Samples/BmpView/res/Toolbar.bmp
new file mode 100644 (file)
index 0000000..a19f239
Binary files /dev/null and b/include/WTL/Samples/BmpView/res/Toolbar.bmp differ
diff --git a/include/WTL/Samples/BmpView/res/ToolbarCE.bmp b/include/WTL/Samples/BmpView/res/ToolbarCE.bmp
new file mode 100644 (file)
index 0000000..03fd70c
Binary files /dev/null and b/include/WTL/Samples/BmpView/res/ToolbarCE.bmp differ
diff --git a/include/WTL/Samples/BmpView/resource.h b/include/WTL/Samples/BmpView/resource.h
new file mode 100644 (file)
index 0000000..b43eb24
--- /dev/null
@@ -0,0 +1,34 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by BmpView.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDR_CONTEXTMENU                 201
+#define IDD_PROP_PAGE1                  202
+#define IDD_PROP_PAGE2                  203
+#define IDD_PROP_PAGE3                  204
+#define IDC_TYPE                        1001
+#define IDC_WIDTH                       1002
+#define IDC_HEIGHT                      1003
+#define IDC_HORRES                      1004
+#define IDC_VERTRES                     1005
+#define IDC_BITDEPTH                    1006
+#define IDC_COMPRESSION                 1008
+#define IDC_FILELOCATION                1009
+#define IDC_FILESIZE                    1010
+#define IDC_FILEDATE                    1011
+#define IDC_FILEATTRIB                  1012
+#define ID_RECENT_BTN                   32777
+#define ID_VIEW_PROPERTIES              32778
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        203
+#define _APS_NEXT_COMMAND_VALUE         32780
+#define _APS_NEXT_CONTROL_VALUE         1013
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/BmpView/resourcece.h b/include/WTL/Samples/BmpView/resourcece.h
new file mode 100644 (file)
index 0000000..50be138
--- /dev/null
@@ -0,0 +1,34 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+// Used by BmpViewCE.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDR_CONTEXTMENU                 201
+#define IDD_PROP_PAGE1                  202
+#define IDD_PROP_PAGE2                  203
+#define IDD_PROP_PAGE3                  204
+#define IDC_TYPE                        1001
+#define IDC_WIDTH                       1002
+#define IDC_HEIGHT                      1003
+#define IDC_HORRES                      1004
+#define IDC_VERTRES                     1005
+#define IDC_BITDEPTH                    1006
+#define IDC_COMPRESSION                 1008
+#define IDC_FILELOCATION                1009
+#define IDC_FILESIZE                    1010
+#define IDC_FILEDATE                    1011
+#define IDC_FILEATTRIB                  1012
+#define ID_RECENT_BTN                   32777
+#define ID_VIEW_PROPERTIES              32778
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        203
+#define _APS_NEXT_COMMAND_VALUE         32780
+#define _APS_NEXT_CONTROL_VALUE         1013
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/BmpView/resourceppc.h b/include/WTL/Samples/BmpView/resourceppc.h
new file mode 100644 (file)
index 0000000..369d9cb
--- /dev/null
@@ -0,0 +1,34 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+// Used by BmpViewPPC.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDR_CONTEXTMENU                 201
+#define IDD_PROP_PAGE1                  202
+#define IDD_PROP_PAGE2                  203
+#define IDD_PROP_PAGE3                  204
+#define IDC_TYPE                        1001
+#define IDC_WIDTH                       1002
+#define IDC_HEIGHT                      1003
+#define IDC_HORRES                      1004
+#define IDC_VERTRES                     1005
+#define IDC_BITDEPTH                    1006
+#define IDC_COMPRESSION                 1008
+#define IDC_FILELOCATION                1009
+#define IDC_FILESIZE                    1010
+#define IDC_FILEDATE                    1011
+#define IDC_FILEATTRIB                  1012
+#define ID_RECENT_BTN                   32777
+#define ID_VIEW_PROPERTIES              32778
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        203
+#define _APS_NEXT_COMMAND_VALUE         32780
+#define _APS_NEXT_CONTROL_VALUE         1013
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/BmpView/stdafx.cpp b/include/WTL/Samples/BmpView/stdafx.cpp
new file mode 100644 (file)
index 0000000..bebfeb8
--- /dev/null
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     BmpView.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700) && !defined(_WIN32_WCE)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700) && !defined(_WIN32_WCE)
diff --git a/include/WTL/Samples/BmpView/stdafx.h b/include/WTL/Samples/BmpView/stdafx.h
new file mode 100644 (file)
index 0000000..14c7ebc
--- /dev/null
@@ -0,0 +1,26 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#ifndef __STDAFX_H__
+#define __STDAFX_H__
+
+// Change these values to use different versions
+#define WINVER         0x0400
+#define _WIN32_IE      0x0400
+#define _RICHEDIT_VER  0x0100
+
+#ifdef WIN32_PLATFORM_PSPC
+#include <aygshell.h>
+#endif // WIN32_PLATFORM_PSPC
+
+#include <atlbase.h>
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#include <atlwin.h>
+
+#endif // __STDAFX_H__
+#pragma comment(lib,"atlthunk.lib")
\ No newline at end of file
diff --git a/include/WTL/Samples/BmpView/view.h b/include/WTL/Samples/BmpView/view.h
new file mode 100644 (file)
index 0000000..4956b2f
--- /dev/null
@@ -0,0 +1,107 @@
+// View.h : interface of the CBitmapView class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __VIEW_H__
+#define __VIEW_H__
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+
+class CBitmapView : public CScrollWindowImpl<CBitmapView>
+{
+public:
+#ifndef _WIN32_WCE
+       DECLARE_WND_CLASS_EX(NULL, 0, -1)
+#else // _WIN32_WCE
+       DECLARE_WND_CLASS(NULL)
+#endif // _WIN32_WCE
+
+       CBitmap m_bmp;
+       SIZE m_size;
+
+
+       CBitmapView()
+       {
+               m_size.cx = m_size.cy = 1;
+       }
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               pMsg;
+               return FALSE;
+       }
+
+       void SetBitmap(HBITMAP hBitmap)
+       {
+               if(!m_bmp.IsNull())
+                       m_bmp.DeleteObject();
+
+               m_bmp = hBitmap;
+
+               if(!m_bmp.IsNull())
+                       m_bmp.GetSize(m_size);
+               else
+                       m_size.cx = m_size.cy = 1;
+
+               SetScrollOffset(0, 0, FALSE);
+               SetScrollSize(m_size);
+       }
+
+       BEGIN_MSG_MAP(CBitmapView)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+               CHAIN_MSG_MAP(CScrollWindowImpl<CBitmapView>);
+       END_MSG_MAP()
+
+       LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               RECT rect;
+               GetClientRect(&rect);
+               int x = 0;
+               int y = 0;
+               if(!m_bmp.IsNull())
+               {
+                       x = m_size.cx + 1;
+                       y = m_size.cy + 1; 
+               }
+               CDCHandle dc = (HDC)wParam;
+               if(rect.right > m_sizeAll.cx)
+               {
+                       RECT rectRight = rect;
+                       rectRight.left = x;
+                       rectRight.bottom = y;
+                       dc.FillRect(&rectRight, COLOR_WINDOW);
+               }
+               if(rect.bottom > m_sizeAll.cy)
+               {
+                       RECT rectBottom = rect;
+                       rectBottom.top = y;
+                       dc.FillRect(&rectBottom, COLOR_WINDOW);
+               }
+#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+               if(!m_bmp.IsNull())
+               {
+                       dc.MoveTo(m_size.cx, 0);
+                       dc.LineTo(m_size.cx, m_size.cy);
+                       dc.LineTo(0, m_size.cy);
+               }
+#endif //!defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
+               return 0;
+       }
+
+       void DoPaint(CDCHandle dc)
+       {
+               if(!m_bmp.IsNull())
+               {
+                       CDC dcMem;
+                       dcMem.CreateCompatibleDC(dc);
+                       HBITMAP hBmpOld = dcMem.SelectBitmap(m_bmp);
+                       dc.BitBlt(0, 0, m_size.cx, m_size.cy, dcMem, 0, 0, SRCCOPY);
+                       dcMem.SelectBitmap(hBmpOld);
+               }
+       }
+};
+
+#endif // __VIEW_H__
diff --git a/include/WTL/Samples/GuidGen/GuidGen.cpp b/include/WTL/Samples/GuidGen/GuidGen.cpp
new file mode 100644 (file)
index 0000000..d8e62f7
--- /dev/null
@@ -0,0 +1,58 @@
+// GuidGen.cpp : 
+//
+
+#include "stdatl.h"
+
+#include <atlframe.h>
+#include <atlgdi.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+
+#include "resource.h"
+
+
+#include "aboutdlg.h"
+#include "maindlg.h"
+
+CAppModule _Module;
+
+
+int Run(LPTSTR /*lpCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       CMainDlg dlgMain;
+
+       if(dlgMain.Create(NULL) == NULL)
+       {
+               ATLTRACE(_T("Main dialog creation failed!\n"));
+               return 0;
+       }
+
+       dlgMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+       
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int nCmdShow)
+{
+#if (_WIN32_IE >= 0x0300)
+       INITCOMMONCONTROLSEX iccx;
+       iccx.dwSize = sizeof(iccx);
+       iccx.dwICC = ICC_BAR_CLASSES;   // change to support other controls
+       ::InitCommonControlsEx(&iccx);
+#else
+       ::InitCommonControls();
+#endif
+
+       _Module.Init(NULL, hInstance);
+
+       int nRet = Run(lpCmdLine, nCmdShow);
+
+       _Module.Term();
+       return nRet;
+}
diff --git a/include/WTL/Samples/GuidGen/GuidGen.sln b/include/WTL/Samples/GuidGen/GuidGen.sln
new file mode 100644 (file)
index 0000000..462a782
--- /dev/null
@@ -0,0 +1,17 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GuidGen", "GuidGen.vcxproj", "{DDDDC333-FE87-DB47-EAA5-AB191D3EB0C3}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {DDDDC333-FE87-DB47-EAA5-AB191D3EB0C3}.Debug|Win32.ActiveCfg = Debug|Win32
+               {DDDDC333-FE87-DB47-EAA5-AB191D3EB0C3}.Release|Win32.ActiveCfg = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/GuidGen/GuidGen.suo b/include/WTL/Samples/GuidGen/GuidGen.suo
new file mode 100644 (file)
index 0000000..8ecdc5a
Binary files /dev/null and b/include/WTL/Samples/GuidGen/GuidGen.suo differ
diff --git a/include/WTL/Samples/GuidGen/GuidGen.vcxproj b/include/WTL/Samples/GuidGen/GuidGen.vcxproj
new file mode 100644 (file)
index 0000000..106678c
--- /dev/null
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <SccProjectName />
+    <SccLocalPath />
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;STRICT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>stdatl.h</PrecompiledHeaderFile>
+      <PrecompiledHeaderOutputFile>.\Debug/GuidGen.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+      <ObjectFileName>.\Debug/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+      <WarningLevel>Level3</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
+      <AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>.\Debug/GuidGen.exe</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>.\Debug/GuidGen.pdb</ProgramDatabaseFile>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Debug/GuidGen.tlb</TypeLibraryName>
+    </Midl>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+      <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+      <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;STRICT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <StringPooling>true</StringPooling>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>stdatl.h</PrecompiledHeaderFile>
+      <PrecompiledHeaderOutputFile>.\Release/GuidGen.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+      <ObjectFileName>.\Release/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+      <WarningLevel>Level3</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
+      <AdditionalDependencies>comctl32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>.\Release/GuidGen.exe</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <ProgramDatabaseFile>.\Release/GuidGen.pdb</ProgramDatabaseFile>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Release/GuidGen.tlb</TypeLibraryName>
+    </Midl>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+      <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="GuidGen.cpp" />
+    <ClCompile Include="stdatl.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="GuidGen.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="aboutdlg.h" />
+    <ClInclude Include="maindlg.h" />
+    <ClInclude Include="resource.h" />
+    <ClInclude Include="stdatl.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\GuidGen.exe.manifest" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\GuidGen.ico" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/GuidGen/GuidGen.vcxproj.filters b/include/WTL/Samples/GuidGen/GuidGen.vcxproj.filters
new file mode 100644 (file)
index 0000000..27d92d0
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{b670eb80-e279-4257-a03f-e304344af633}</UniqueIdentifier>
+      <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{bbdbcbb2-d073-447e-8b6c-368f2c8fb7b0}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{65240229-f4e6-460a-8a4f-950e5efb37e9}</UniqueIdentifier>
+      <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="GuidGen.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="stdatl.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="GuidGen.rc">
+      <Filter>Source Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="aboutdlg.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="maindlg.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="resource.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="stdatl.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\GuidGen.exe.manifest">
+      <Filter>Resource Files</Filter>
+    </Manifest>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\GuidGen.ico">
+      <Filter>Resource Files</Filter>
+    </None>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/GuidGen/GuidGen.vcxproj.user b/include/WTL/Samples/GuidGen/GuidGen.vcxproj.user
new file mode 100644 (file)
index 0000000..ace9a86
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/GuidGen/aboutdlg.h b/include/WTL/Samples/GuidGen/aboutdlg.h
new file mode 100644 (file)
index 0000000..d488587
--- /dev/null
@@ -0,0 +1,23 @@
+class CAboutDlg : public CDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTBOX };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+               return TRUE;
+       }
+
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/GuidGen/maindlg.h b/include/WTL/Samples/GuidGen/maindlg.h
new file mode 100644 (file)
index 0000000..0821b8e
--- /dev/null
@@ -0,0 +1,261 @@
+// maindlg.h : interface of the CMainDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MAINDLG_H__6920296A_4C3F_11D1_AA9A_000000000000__INCLUDED_)
+#define AFX_MAINDLG_H__6920296A_4C3F_11D1_AA9A_000000000000__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+class CMainDlg : public CDialogImpl<CMainDlg>, public CMessageFilter
+{
+public:
+       enum { IDD = IDD_GUIDGEN_DIALOG };
+
+       int m_nGuidType;
+       GUID m_guid;
+
+       CMainDlg() : m_nGuidType(0)
+       {
+       }
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               return ::IsDialogMessage(m_hWnd, pMsg);
+       }
+
+       void UpdateData()
+       {
+               m_nGuidType = 0;
+               m_nGuidType = IsDlgButtonChecked(IDC_RADIO2) ? 1 : m_nGuidType;
+               m_nGuidType = IsDlgButtonChecked(IDC_RADIO3) ? 2 : m_nGuidType;
+               m_nGuidType = IsDlgButtonChecked(IDC_RADIO4) ? 3 : m_nGuidType;
+               _ASSERTE(m_nGuidType >= 0 && m_nGuidType <= 3);
+       }
+
+       BEGIN_MSG_MAP(CMainDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnOK)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+               COMMAND_ID_HANDLER(IDC_NEWGUID, OnNewGUID)
+               COMMAND_RANGE_HANDLER(IDC_RADIO1, IDC_RADIO4, OnSelChange)
+               MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // center the dialog on the screen
+               CenterWindow();
+
+               // set icons
+               HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+               SetIcon(hIcon, TRUE);
+               HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+               SetIcon(hIconSmall, FALSE);
+
+               // Add "About..." menu item to system menu.
+
+               // IDM_ABOUTBOX must be in the system command range.
+               _ASSERTE((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+               _ASSERTE(IDM_ABOUTBOX < 0xF000);
+
+               CMenu SysMenu = GetSystemMenu(FALSE);
+               if(::IsMenu(SysMenu))
+               {
+                       TCHAR szAboutMenu[256];
+                       if(::LoadString(_Module.GetResourceInstance(), IDS_ABOUTBOX, szAboutMenu, 255) > 0)
+                       {
+                               SysMenu.AppendMenu(MF_SEPARATOR);
+                               SysMenu.AppendMenu(MF_STRING, IDM_ABOUTBOX, szAboutMenu);
+                       }
+               }
+               SysMenu.Detach();
+
+               // register object for message filtering
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               pLoop->AddMessageFilter(this);
+
+               CRegKey reg;
+               long lRet = reg.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\ATL\\Samples\\GUIDGEN"), KEY_READ);
+               if(lRet == ERROR_SUCCESS)
+               {
+                       DWORD dwVal;
+#if (_ATL_VER >= 0x0700)
+                       lRet = reg.QueryDWORDValue(_T("GUID Type"), dwVal);
+#else
+                       lRet = reg.QueryValue(dwVal, _T("GUID Type"));
+#endif
+                       if(lRet == ERROR_SUCCESS)
+                               m_nGuidType = (int)dwVal;
+               }
+               CheckRadioButton(IDC_RADIO1, IDC_RADIO4, IDC_RADIO1 + m_nGuidType);
+
+               if(!NewGUID())
+                       CloseDialog(IDABORT);
+
+               DisplayGUID();
+
+               return TRUE;
+       }
+
+       void GetFormattedGuid(TCHAR* rString)
+       {
+               // load appropriate formatting string
+               TCHAR szBuf[256];
+               ::LoadString(_Module.GetResourceInstance(), IDS_FORMATS+m_nGuidType, szBuf, 255);
+               wsprintf(rString, szBuf, 
+                       // first copy...
+                       m_guid.Data1, m_guid.Data2, m_guid.Data3, 
+                       m_guid.Data4[0], m_guid.Data4[1], m_guid.Data4[2], m_guid.Data4[3],
+                       m_guid.Data4[4], m_guid.Data4[5], m_guid.Data4[6], m_guid.Data4[7],
+                       // second copy...
+                       m_guid.Data1, m_guid.Data2, m_guid.Data3, 
+                       m_guid.Data4[0], m_guid.Data4[1], m_guid.Data4[2], m_guid.Data4[3],
+                       m_guid.Data4[4], m_guid.Data4[5], m_guid.Data4[6], m_guid.Data4[7]);
+       }
+
+       void DisplayGUID()
+       {
+               TCHAR szBuf[512];
+               GetFormattedGuid(szBuf);
+               SetDlgItemText(IDC_RESULTS, szBuf);
+       }
+
+       BOOL NewGUID()
+       {
+               m_guid = GUID_NULL;
+               ::CoCreateGuid(&m_guid);
+               if(m_guid == GUID_NULL)
+               {
+                       TCHAR szBuf[256];
+                       ::LoadString(_Module.GetResourceInstance(), IDP_ERR_CREATE_GUID, szBuf, 255);
+                       MessageBox(szBuf, _T("GUIDGen"), MB_OK);
+                       return FALSE;
+               }
+               return TRUE;
+       }
+
+       LRESULT OnNewGUID(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               if(!NewGUID())
+                       return 0;
+               DisplayGUID();
+               return 0;
+       }
+       
+       LRESULT OnSelChange(WORD wNotifyCode, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               if(wNotifyCode == BN_CLICKED)
+               {
+                       UpdateData();
+                       DisplayGUID();
+               }
+               return 0;
+       }
+
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               UpdateData();
+               if(!OpenClipboard())
+               {
+                       TCHAR szBuf[256];
+                       ::LoadString(_Module.GetResourceInstance(), IDP_ERR_OPEN_CLIP, szBuf, 255);
+                       MessageBox(szBuf, _T("GUIDGen"), MB_OK);
+                       return 0;
+               }
+
+               TCHAR strResult[512];
+               GetFormattedGuid(strResult);
+               int nTextLen = (lstrlen(strResult) + 1) * sizeof(TCHAR);
+               HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nTextLen);
+               if(hGlobal != NULL)
+               {
+                       LPVOID lpText = GlobalLock(hGlobal);
+                       memcpy(lpText, strResult, nTextLen);
+
+                       EmptyClipboard();
+                       GlobalUnlock(hGlobal);
+#ifdef _UNICODE
+                       SetClipboardData(CF_UNICODETEXT, hGlobal);
+#else
+                       SetClipboardData(CF_TEXT, hGlobal);
+#endif
+               }
+               CloseClipboard();
+
+               return 0;
+       }
+
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CRegKey reg;
+               long lRet = reg.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\ATL\\Samples\\GUIDGen"), KEY_WRITE);
+               if(lRet != ERROR_SUCCESS)
+               {
+                       lRet = reg.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft"), KEY_WRITE);
+                       if(lRet == ERROR_SUCCESS)
+                       {
+                               CRegKey reg1;
+                               lRet = reg1.Create(reg.m_hKey, _T("ATL"), REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE);
+                               if(lRet == ERROR_SUCCESS)
+                               {
+                                       CRegKey reg2;
+                                       lRet = reg2.Create(reg1.m_hKey, _T("Samples"), REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE);
+                                       if(lRet == ERROR_SUCCESS)
+                                       {
+                                               CRegKey reg3;
+                                               lRet = reg3.Create(reg2.m_hKey, _T("GUIDGen"), REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE);
+                                               reg.Close();
+                                               lRet = reg.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\ATL\\Samples\\GUIDGen"), KEY_WRITE);
+                                       }
+                               }
+                       }
+               }
+
+               if(lRet == ERROR_SUCCESS)
+               {
+                       DWORD dwVal = m_nGuidType;
+#if (_ATL_VER >= 0x0700)
+                       reg.SetDWORDValue(_T("GUID Type"), dwVal);
+#else
+                       reg.SetValue(dwVal, _T("GUID Type"));
+#endif
+               }
+
+               CloseDialog(wID);
+               return 0;
+       }
+
+       void CloseDialog(int nVal)
+       {
+               DestroyWindow();
+               ::PostQuitMessage(nVal);
+       }
+
+       LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               UINT uCmdType = (UINT)wParam;
+
+               if((uCmdType & 0xFFF0) == IDM_ABOUTBOX)
+               {
+                       CAboutDlg dlg;
+                       dlg.DoModal();
+               }
+               else
+                       bHandled = FALSE;
+
+               return 0;
+       }
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAINDLG_H__6920296A_4C3F_11D1_AA9A_000000000000__INCLUDED_)
diff --git a/include/WTL/Samples/GuidGen/res/GuidGen.ico b/include/WTL/Samples/GuidGen/res/GuidGen.ico
new file mode 100644 (file)
index 0000000..16b86fc
Binary files /dev/null and b/include/WTL/Samples/GuidGen/res/GuidGen.ico differ
diff --git a/include/WTL/Samples/GuidGen/resource.h b/include/WTL/Samples/GuidGen/resource.h
new file mode 100644 (file)
index 0000000..18c88ef
--- /dev/null
@@ -0,0 +1,33 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by GuidGen.rc
+//
+#define IDM_ABOUTBOX                    0x0010
+#define IDD_ABOUTBOX                    100
+#define IDD_GUIDGEN_DIALOG              102
+#define IDP_ERR_INIT_OLE                102
+#define IDS_FORMATS                     104
+#define IDS_STRING105                   105
+#define IDS_STRING106                   106
+#define IDS_STRING107                   107
+#define IDR_MAINFRAME                   128
+#define IDC_RADIO1                      1000
+#define IDC_RADIO2                      1001
+#define IDC_RADIO3                      1002
+#define IDC_RADIO4                      1003
+#define IDC_RESULTS                     1004
+#define IDC_NEWGUID                     1005
+#define IDP_ERR_CREATE_GUID             2000
+#define IDP_ERR_OPEN_CLIP               2001
+#define IDS_ABOUTBOX                    2002
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32772
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           102
+#endif
+#endif
diff --git a/include/WTL/Samples/GuidGen/resourcece.h b/include/WTL/Samples/GuidGen/resourcece.h
new file mode 100644 (file)
index 0000000..18c88ef
--- /dev/null
@@ -0,0 +1,33 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by GuidGen.rc
+//
+#define IDM_ABOUTBOX                    0x0010
+#define IDD_ABOUTBOX                    100
+#define IDD_GUIDGEN_DIALOG              102
+#define IDP_ERR_INIT_OLE                102
+#define IDS_FORMATS                     104
+#define IDS_STRING105                   105
+#define IDS_STRING106                   106
+#define IDS_STRING107                   107
+#define IDR_MAINFRAME                   128
+#define IDC_RADIO1                      1000
+#define IDC_RADIO2                      1001
+#define IDC_RADIO3                      1002
+#define IDC_RADIO4                      1003
+#define IDC_RESULTS                     1004
+#define IDC_NEWGUID                     1005
+#define IDP_ERR_CREATE_GUID             2000
+#define IDP_ERR_OPEN_CLIP               2001
+#define IDS_ABOUTBOX                    2002
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32772
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           102
+#endif
+#endif
diff --git a/include/WTL/Samples/GuidGen/stdatl.cpp b/include/WTL/Samples/GuidGen/stdatl.cpp
new file mode 100644 (file)
index 0000000..cfb9099
--- /dev/null
@@ -0,0 +1,9 @@
+// stdatl.cpp : source file that includes just the standard includes
+//     GuidGen.pch will be the pre-compiled header
+//     stdatl.obj will contain the pre-compiled type information
+
+#include "stdatl.h"
+
+#if (_ATL_VER < 0x0700) && !defined(_WIN32_WCE)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
diff --git a/include/WTL/Samples/GuidGen/stdatl.h b/include/WTL/Samples/GuidGen/stdatl.h
new file mode 100644 (file)
index 0000000..534af14
--- /dev/null
@@ -0,0 +1,20 @@
+// stdatl.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+// Change these values to use different versions
+#define _WIN32_IE      0x0400
+#define _RICHEDIT_VER  0x0100
+
+#include <atlbase.h>
+#include <atlapp.h>
+#include <atlstdthunk.h>
+
+extern CAppModule _Module;
+
+#include <atlwin.h>
+#pragma comment(lib,"atlthunk.lib")
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
diff --git a/include/WTL/Samples/ImageView/ImageView.cpp b/include/WTL/Samples/ImageView/ImageView.cpp
new file mode 100644 (file)
index 0000000..66d4874
--- /dev/null
@@ -0,0 +1,53 @@
+// ImageView.cpp : main source file for ImageView.exe
+//
+
+#include "stdafx.h"
+
+#if (_WTL_VER < 0x0750) 
+       #error ImageView requires WTL version 7.5 or higher
+#endif
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+
+#define _ATL_USE_CSTRING_FLOAT
+#include <atlmisc.h>
+#include <atlscrl.h>
+
+#include <atlwince.h>
+
+#include "resource.h"
+
+#include "ImageViewView.h"
+#include "ImageViewdlg.h"
+#include "MainFrm.h"
+
+CAppModule _Module;
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+
+       HRESULT hRes = CMainFrame::ActivatePreviousInstance(hInstance, lpstrCmdLine );
+       
+       if(FAILED(hRes) || S_FALSE == hRes)
+       {
+               return hRes;
+       }
+
+       hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       AtlInitCommonControls(ICC_DATE_CLASSES);
+       SHInitExtraControls();
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       int nRet = CMainFrame::AppRun(lpstrCmdLine, nCmdShow);
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/Samples/ImageView/ImageView.sln b/include/WTL/Samples/ImageView/ImageView.sln
new file mode 100644 (file)
index 0000000..74af69b
--- /dev/null
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageView", "ImageView.vcproj", "{AA45B2CC-BACC-431F-A208-8A36CBACB445}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+               Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+               Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+               Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+               Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {AA45B2CC-BACC-431F-A208-8A36CBACB445}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/ImageView/ImageView.suo b/include/WTL/Samples/ImageView/ImageView.suo
new file mode 100644 (file)
index 0000000..c72177e
Binary files /dev/null and b/include/WTL/Samples/ImageView/ImageView.suo differ
diff --git a/include/WTL/Samples/ImageView/ImageView.vcxproj b/include/WTL/Samples/ImageView/ImageView.vcxproj
new file mode 100644 (file)
index 0000000..56ddd53
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Template|Win32">
+      <Configuration>Template</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+
+  <PropertyGroup Label="Globals">
+  </PropertyGroup>
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Template|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+  </PropertyGroup>
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup />
+
+  <ItemDefinitionGroup></ItemDefinitionGroup>
+  <ItemGroup></ItemGroup>
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
diff --git a/include/WTL/Samples/ImageView/ImageView.vcxproj.user b/include/WTL/Samples/ImageView/ImageView.vcxproj.user
new file mode 100644 (file)
index 0000000..ace9a86
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/ImageView/ImageViewdlg.h b/include/WTL/Samples/ImageView/ImageViewdlg.h
new file mode 100644 (file)
index 0000000..bab2788
--- /dev/null
@@ -0,0 +1,523 @@
+// ImageViewdlg.h : interface of the ImageView dialog and property sheet and pages classes
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(_IMAGEVIEW_DLG_H__)
+#define _IMAGEVIEW_DLG_H__
+
+#pragma once
+
+class CMainFrame; // forward declaration
+
+/////////////////////
+// CAboutDlg 
+
+class CAboutDlg : public CStdSimpleDialogResizeImpl<CAboutDlg, 
+       IDD_ABOUTBOX, SHIDIF_DONEBUTTON | SHIDIF_FULLSCREENNOMENUBAR>
+{
+public:
+       BEGIN_DLGRESIZE_MAP(CAboutDlg)
+               BEGIN_DLGRESIZE_GROUP()
+                       DLGRESIZE_CONTROL(IDC_HEAD, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_APPICON, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_INFOSTATIC, DLSZ_SIZE_X | DLSZ_SIZE_Y)
+               END_DLGRESIZE_GROUP()
+       END_DLGRESIZE_MAP()
+};
+
+/////////////////////
+// CMoveDlg :  Called by CRegisterDlg to move ImageView.exe to \Windows folder
+
+class CMoveDlg : public  CStdDialogResizeImpl<CMoveDlg,SHIDIF_FULLSCREENNOMENUBAR>
+{
+public:
+       CString m_sAppPath;
+       CString m_sApp;
+
+       enum { IDD = IDD_MOVE };
+
+       typedef CStdDialogResizeImpl<CMoveDlg,SHIDIF_FULLSCREENNOMENUBAR> baseClass;
+
+       BEGIN_DLGRESIZE_MAP(CMoveDlg)
+               BEGIN_DLGRESIZE_GROUP()
+                       DLGRESIZE_CONTROL(IDC_FILELOCATION_H, DLSZ_SIZE_X | DLSZ_SIZE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILELOCATION, DLSZ_SIZE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_INFOSTATIC, DLSZ_SIZE_X | DLSZ_SIZE_Y)
+                       DLGRESIZE_CONTROL(IDC_SHORTCUT, DLSZ_SIZE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_MOVE_T, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_MOVE, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+               END_DLGRESIZE_GROUP()
+       END_DLGRESIZE_MAP()
+
+       BEGIN_MSG_MAP(CMoveDlg)
+               COMMAND_HANDLER(IDC_MOVE, BN_CLICKED, OnMove)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+               
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               SHDoneButton( m_hWnd, SHDB_HIDE);
+
+               GetModuleFileName( NULL, m_sAppPath.GetBuffer(MAX_PATH+1), MAX_PATH);
+               m_sAppPath.ReleaseBuffer();
+
+               SetDlgItemText( IDC_FILELOCATION, m_sAppPath);
+               m_sApp = m_sAppPath.Mid( m_sAppPath.ReverseFind(L'\\') + 1);
+               
+               CheckDlgButton( IDC_SHORTCUT, TRUE);
+
+               return bHandled=FALSE;
+       }
+
+// Move operation
+       LRESULT OnMove(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CString sDest = L"\\Windows\\" + m_sApp;
+               if ( ::MoveFile( m_sAppPath, sDest))
+               {
+                       if ( IsDlgButtonChecked( IDC_SHORTCUT))
+                       {
+                               m_sAppPath.Replace( L".exe", L".lnk");
+                               if ( !::SHCreateShortcut( (LPTSTR)(LPCTSTR)m_sAppPath, (LPTSTR)(LPCTSTR)sDest))
+                                       AtlMessageBox( m_hWnd, L"Cannot create shortcut to ImageView.", 
+                                               IDR_MAINFRAME, MB_OK | MB_ICONWARNING);
+                       }
+                       EndDialog(IDOK);
+               }
+               else
+                       AtlMessageBox( m_hWnd, L"Cannot move ImageView.exe to \\Windows folder.", 
+                               IDR_MAINFRAME, MB_OK | MB_ICONERROR);
+               return 0;
+       }
+};
+
+/////////////////////
+// CRegisterDlg: Register ImageView.exe as standard program for image files 
+
+#ifdef _WTL_CE_DRA
+class CRegisterDlg : public  CStdOrientedDialogImpl<CRegisterDlg, SHIDIF_DONEBUTTON | SHIDIF_FULLSCREENNOMENUBAR>
+#else
+class CRegisterDlg : public  CStdDialogResizeImpl<CRegisterDlg, SHIDIF_DONEBUTTON | SHIDIF_FULLSCREENNOMENUBAR>
+#endif
+{
+public:
+
+#ifdef _WTL_CE_DRA
+       typedef CStdOrientedDialogImpl<CRegisterDlg, SHIDIF_DONEBUTTON | SHIDIF_FULLSCREENNOMENUBAR> baseClass;
+       enum {IDD = IDD_REGISTER, IDD_LANDSCAPE = IDD_REGISTER_L};
+#else
+       typedef CStdDialogResizeImpl<CRegisterDlg, SHIDIF_DONEBUTTON | SHIDIF_FULLSCREENNOMENUBAR> baseClass;
+       enum {IDD = IDD_REGISTER};
+#endif // _WTL_CE_DRA
+
+       CString m_sAppPath;
+       CString m_sApp;
+
+// Image type enumeration
+       enum ImageType { BMP = IDC_BMP, JPG, PNG, GIF } ;
+
+// Implementation
+// Helper class: image command registry key
+       class CImageTypeKey : public CRegKey
+       {
+       public:
+               CString m_sCmd;
+               DWORD size;
+
+               CImageTypeKey( ImageType typ) : size( MAX_PATH)
+               {
+                       CString sKey = GetTypeString( typ);
+                       sKey += L"\\Shell\\Open\\Command";
+                       Open( HKEY_CLASSES_ROOT, sKey);
+               }
+
+               LPCTSTR GetTypeString( ImageType typ)
+               {
+                       switch ( typ)
+                       {
+                       case BMP : return L"bmpimage"; 
+                       case JPG : return L"jpegimage"; 
+                       case PNG : return L"pngimage"; 
+                       case GIF : return L"gifimage"; 
+                       default : ATLASSERT( FALSE); return NULL;
+                       }
+               }
+
+               LPCTSTR GetCmd()
+               {
+#if _ATL_VER <0x800
+                       QueryValue( m_sCmd.GetBuffer( size), L"", &size);
+#else
+                       QueryStringValue(L"",  m_sCmd.GetBuffer( size), &size);
+#endif // _ATL_VER <0x800
+                       m_sCmd.ReleaseBuffer();
+                       return m_sCmd;
+               }
+
+               void SetCmd(LPCTSTR sCmd)
+               {
+#if _ATL_VER <0x800
+                       SetValue( sCmd, L"");
+#else
+                       SetStringValue(L"", sCmd);
+#endif // _ATL_VER <0x800
+               }
+       };
+
+// Image type file extension
+               LPCTSTR GetExtString( ImageType typ)
+               {
+                       switch ( typ)
+                       {
+                       case BMP : return L".bmp"; ;
+                       case JPG : return L".jpg"; 
+                       case PNG : return L".png"; 
+                       case GIF : return L".gif"; 
+                       default : ATLASSERT( FALSE); return NULL;
+                       }
+               }
+
+// Image type registration status
+       bool IsRegistered( ImageType typ)
+       {
+               CImageTypeKey key( typ);
+               CString sCmd = key.GetCmd();
+               return sCmd.Find( m_sApp) != -1 ;               
+       }
+       
+// Image type registration-deregistration
+       void Register( ImageType typ, BOOL bRegister)
+       {
+               CImageTypeKey key( typ);
+               CString sOldCmd = key.GetCmd();
+               CString sNewCmd = m_sAppPath;
+               CAppInfoT<CMainFrame> info;
+
+               if ( bRegister)
+                       sNewCmd += L" %1";
+               else
+                       info.Restore( sNewCmd, key.GetTypeString( typ));
+               
+               key.SetCmd( sNewCmd);
+               
+               if ( bRegister)
+                       info.Save( sOldCmd, key.GetTypeString( typ));
+               else 
+                       info.Delete( key.GetTypeString( typ));
+       }
+       
+#ifndef _WTL_CE_DRA
+       BEGIN_DLGRESIZE_MAP(CMoveDlg)
+               BEGIN_DLGRESIZE_GROUP()
+                       DLGRESIZE_CONTROL(IDC_INFOSTATIC, DLSZ_SIZE_X | DLSZ_SIZE_Y)
+                       DLGRESIZE_CONTROL(IDC_REGISTER_H, DLSZ_SIZE_X | DLSZ_SIZE_Y)
+                       DLGRESIZE_CONTROL(IDC_IBMP, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_BMP, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_IJPG, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_JPG, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_IPNG, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_PNG, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_IGIF, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_GIF, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+               END_DLGRESIZE_GROUP()
+       END_DLGRESIZE_MAP()
+#else
+       void OnOrientation(DRA::DisplayMode mode)
+       {
+// Text controls re-initialization
+               for(int iBtn = IDC_BMP ; iBtn <= IDC_GIF ; iBtn++)
+               {
+                       SHFILEINFO sfi;
+                       ::SHGetFileInfo( GetExtString( (ImageType)iBtn), FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), 
+                               SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME );
+                       SetDlgItemText( iBtn, sfi.szTypeName);
+                       CheckDlgButton( iBtn, IsRegistered( (ImageType)iBtn));
+               }
+       }
+#endif // ndef _WTL_CE_DRA
+
+       BEGIN_MSG_MAP(CRegisterDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_RANGE_HANDLER(IDC_BMP, IDC_GIF, OnCheckType)
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+
+// Dialog initialization
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               ::GetModuleFileName( NULL, m_sAppPath.GetBuffer( MAX_PATH + 1), MAX_PATH);
+               m_sAppPath.ReleaseBuffer();
+               m_sApp = m_sAppPath.Mid( m_sAppPath.ReverseFind(L'\\') + 1);
+
+               // Call CMoveDlg if ImageView.exe is not located in \Windows folder
+               if( CString(L"\\Windows\\") + m_sApp != m_sAppPath)
+               {
+                       CMoveDlg dlg;
+                       if ( dlg.DoModal() == IDCANCEL)
+                               EndDialog( IDCANCEL);/**/
+
+                       ::GetModuleFileName( NULL, m_sAppPath.GetBuffer( MAX_PATH + 1), MAX_PATH);
+                       m_sAppPath.ReleaseBuffer();
+               }
+
+// Controls initialization: IDC_BMP, IDC_JPG etc... MUST be in sequence.
+               for( int iBtn = IDC_BMP, iIcon = IDC_IBMP ; iBtn <= IDC_GIF ; iBtn++, iIcon++)
+               {
+                       SHFILEINFO sfi;
+                       ::SHGetFileInfo( GetExtString( (ImageType)iBtn), FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), 
+                               SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_TYPENAME );
+                       SendDlgItemMessage( iIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)sfi.hIcon);
+                       SetDlgItemText( iBtn, sfi.szTypeName);
+                       CheckDlgButton( iBtn, IsRegistered( (ImageType)iBtn));
+               }
+
+               return bHandled = FALSE; // to prevent CDialogImplBaseT< TBase >::DialogProc settings
+       }
+
+// Operation
+       LRESULT OnCheckType(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               Register( (ImageType)wID, IsDlgButtonChecked( wID));
+               return 0;
+       }
+};
+
+
+/////////////////////
+// CFilePage: Current image file propertes 
+
+class CFilePage : public CPropertyPageImpl<CFilePage>, public CDialogResize<CFilePage>
+{
+public:
+       enum { IDD = IDD_PROP_FILE };
+
+       CString m_sPath;
+
+       CFilePage( LPCTSTR sPath) : m_sPath( sPath) { }
+
+       BEGIN_DLGRESIZE_MAP(CMoveDlg)
+               BEGIN_DLGRESIZE_GROUP()
+                       DLGRESIZE_CONTROL(IDC_TYPENAME_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_TYPENAME, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILEICON, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILELOCATION_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILELOCATION, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILENAME_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILENAME, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILESIZE_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILESIZE, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILEDATE_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILEDATE, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILEATTRIB_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_FILEATTRIB, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+               END_DLGRESIZE_GROUP()
+       END_DLGRESIZE_MAP()
+
+       BEGIN_MSG_MAP(CFilePage)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_SIZE, CDialogResize<CFilePage>::OnSize)
+               CHAIN_MSG_MAP(CPropertyPageImpl<CFilePage>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               ATLASSERT( !m_sPath.IsEmpty()); 
+
+               CString s;
+
+
+               SHFILEINFO sfi;
+               ::SHGetFileInfo( m_sPath, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_TYPENAME);
+               SendDlgItemMessage( IDC_FILEICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)sfi.hIcon);
+               SetDlgItemText( IDC_TYPENAME, sfi.szTypeName);
+               
+               s = m_sPath.Left( m_sPath.ReverseFind(L'\\'));
+
+               SetDlgItemText( IDC_FILELOCATION, s);
+               SetDlgItemText( IDC_FILENAME, m_sPath.Mid( m_sPath.ReverseFind(L'\\') + 1));
+
+               CFindFile ff;
+               ff.FindFile( m_sPath);
+               SetDlgItemInt( IDC_FILESIZE, (UINT)ff.GetFileSize());
+
+               FILETIME ftim;
+               ff.GetCreationTime( &ftim);
+               FormatFileTime( &ftim, s);
+               SetDlgItemText( IDC_FILEDATE, s);
+
+               s.Empty();
+               if ( ff.MatchesMask( FILE_ATTRIBUTE_ENCRYPTED))
+                       s += L"Encrypted, ";
+               if ( ff.IsCompressed())
+                       s += L"Compressed, ";
+               if ( ff.IsArchived())
+                       s += L"Archive, ";
+               if ( ff.IsReadOnly())
+                       s += L"Read-only";
+               
+               if ( s.Find( L", ", s.GetLength() - 2) != -1)
+                       s = s.Left( s.GetLength() - 2);
+               SetDlgItemText( IDC_FILEATTRIB, s);
+
+               DlgResize_Init(FALSE);
+               return TRUE;
+       }
+
+// Implementation 
+       void FormatFileTime( FILETIME *pftim, CString& sDateTime)
+       {
+               SYSTEMTIME stim;
+               CString s;
+               ::FileTimeToSystemTime( pftim, &stim);
+               ::GetDateFormat( LOCALE_USER_DEFAULT, 0, &stim, NULL, sDateTime.GetBuffer(40), 40);
+               sDateTime.ReleaseBuffer();
+               ::GetTimeFormat( LOCALE_USER_DEFAULT, TIME_NOSECONDS, &stim, NULL, s.GetBuffer(40), 40);
+               s.ReleaseBuffer();
+               sDateTime += L"  " + s;
+       }
+
+};
+
+/////////////////////
+// CImagePage: Current image properties 
+
+class CImagePage : public CPropertyPageImpl<CImagePage>,public CDialogResize<CImagePage>
+{
+public:
+       enum { IDD = IDD_PROP_IMAGE };
+       CBitmapHandle m_bmp;
+       
+       CImagePage(HBITMAP hbmp) : m_bmp(hbmp) {}
+
+       BEGIN_DLGRESIZE_MAP(CMoveDlg)
+               BEGIN_DLGRESIZE_GROUP()
+                       DLGRESIZE_CONTROL(IDC_TYPENAME_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_TYPENAME, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_IMAGESIZE_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_IMAGESIZE, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_NUMCOLORS_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_NUMCOLORS, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_BITDEPTH_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_BITDEPTH, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_NUMBYTES_H, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_NUMBYTES, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+                       DLGRESIZE_CONTROL(IDC_IMAGE, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT)
+               END_DLGRESIZE_GROUP()
+       END_DLGRESIZE_MAP()
+
+       BEGIN_MSG_MAP(CImagePage)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_SIZE, CDialogResize<CImagePage>::OnSize)
+               CHAIN_MSG_MAP(CPropertyPageImpl<CImagePage>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               ATLASSERT( !m_bmp.IsNull());
+
+               DIBSECTION ds;
+               ATLVERIFY( ::GetObject( m_bmp, sizeof(DIBSECTION), &ds) == sizeof(DIBSECTION));
+
+               CString s;
+               s.Format( L"(h) %d x (v) %d", ds.dsBmih.biWidth, ds.dsBmih.biHeight);
+               SetDlgItemText( IDC_IMAGESIZE, s);
+               SetDlgItemInt( IDC_BITDEPTH, ds.dsBmih.biBitCount);
+               SetDlgItemInt( IDC_NUMBYTES, ds.dsBmih.biSizeImage);
+               SetDlgItemInt( IDC_NUMCOLORS, AtlGetDibNumColors( &ds.dsBmih));
+
+               CStatic sImg = GetDlgItem( IDC_IMAGE);
+               CRect rectImg;
+               sImg.GetWindowRect( rectImg);
+               CSize sizeImg( ds.dsBmih.biWidth, ds.dsBmih.biHeight);
+               double fzoom = max( (double)sizeImg.cx / rectImg.Width(),
+                                               (double)sizeImg.cy / rectImg.Height());
+
+               CBitmapHandle hbm = AtlCopyBitmap( m_bmp, sizeImg / fzoom, true);
+               sImg.SetBitmap( hbm);
+
+               DlgResize_Init(FALSE);
+               return TRUE;
+       }
+};
+
+/////////////////////
+// CViewPage: Current view properties 
+
+class CViewPage : public CPropertyPageImpl<CViewPage>
+{
+public:
+
+       CImageViewView& m_rview;
+       
+       CViewPage( CImageViewView& rview) : m_rview( rview){}
+
+       enum { IDD = IDD_PROP_VIEW };
+
+       BEGIN_MSG_MAP(CViewPage)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               CHAIN_MSG_MAP(CPropertyPageImpl<CViewPage>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CString s;
+               s.Format( _T("%.2f"), m_rview.GetZoom());
+               SetDlgItemText( IDC_ZOOM, s);
+               s.Format(_T("(h) %d x (v) %d"), m_rview.m_sizeAll.cx, m_rview.m_sizeAll.cy);
+               SetDlgItemText( IDC_IMAGESIZE, s);
+
+               CStatic sImg = GetDlgItem( IDC_VIEW);
+               CRect rectImg;
+               sImg.GetWindowRect( rectImg);
+               double zoom = max( (double)m_rview.GetScrollSize().cx / rectImg.Width(),
+                                               (double)m_rview.GetScrollSize().cy / rectImg.Height());
+               CBitmapHandle hbm = AtlCopyBitmap( m_rview.m_bmp, m_rview.GetScrollSize() / zoom, true);
+
+// Draw view rectangle in image 
+               CDC dc = CreateCompatibleDC( NULL);
+               dc.SelectStockBrush( HOLLOW_BRUSH);
+               HBITMAP bmpOld = dc.SelectBitmap( hbm)
+                       ;
+               CRect rect( CPoint( 0, 0), m_rview.m_sizeClient);
+               m_rview.WndtoTrue( rect);
+               rect = CRect( (CPoint)( CSize( rect.TopLeft()) / zoom), rect.Size() / zoom);
+               CPen pen;
+               pen.CreatePen( PS_SOLID, 2, RGB( 255, 0,  0));
+               HPEN penOld=dc.SelectPen( pen);
+               dc.Rectangle( rect);
+
+               dc.SelectPen( penOld);
+               dc.SelectBitmap( bmpOld);
+               sImg.SetBitmap( hbm);
+               return TRUE;
+       }
+
+};
+
+class CImageProperties : public CPropertySheetImpl<CImageProperties>
+{
+public:
+       CFilePage m_FilePage;
+       CImagePage m_ImagePage;
+       CViewPage m_ViewPage;
+
+       CImageProperties( LPCTSTR sname, CImageViewView & rview) :
+       m_FilePage(sname), m_ImagePage( rview.m_bmp), m_ViewPage( rview) 
+       {
+               SetTitle( rview.m_sImageName);
+
+               if ( *sname )
+                       AddPage( m_FilePage);
+               AddPage( m_ImagePage);
+               AddPage( m_ViewPage);
+       }
+
+       void OnSheetInitialized()
+       {
+               AtlCreateEmptyMenuBar(m_hWnd, false);
+       }
+};
+
+#endif // _IMAGEVIEW_DLG_H__
diff --git a/include/WTL/Samples/ImageView/ImageViewview.h b/include/WTL/Samples/ImageView/ImageViewview.h
new file mode 100644 (file)
index 0000000..0509e76
--- /dev/null
@@ -0,0 +1,281 @@
+// ImageViewView.h : interface of the CImageViewView class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(_IMAGEVIEW_VIEW_H__)
+#define _IMAGEVIEW_VIEW_H__
+
+#pragma once
+
+/////////////////////
+// CImageViewView :  Application view
+
+class CImageViewView : 
+       public CWindowImpl< CImageViewView > ,
+       public CZoomScrollImpl< CImageViewView >        
+{
+public:
+       DECLARE_WND_CLASS(NULL)
+
+       CTrackBarCtrl m_ZoomCtrl;
+       CStatusBarCtrl m_TitleBar;
+
+       CString m_sImageName;
+       CBitmap m_bmp;
+
+       CPoint m_ptMouse;
+       
+       bool m_bShowScroll;
+
+       CImageViewView() : m_bShowScroll( true) {}
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               pMsg;
+               return FALSE;
+       }
+
+// Image operation
+       void SetImage( HBITMAP hBitmap, LPCTSTR sname = NULL, double fZoom = 1.0, POINT pScroll = CPoint( -1,-1))
+       {
+               CSize sizeImage( 1, 1);
+               m_bmp.Attach( hBitmap ); // will delete existing if necessary
+
+               if( m_bmp.IsNull())
+               {
+                       m_sImageName.Empty();
+                       m_ZoomCtrl.ModifyStyle( WS_BORDER, NULL, SWP_DRAWFRAME);
+                       m_TitleBar.SetText( 0, L"No image");
+               }
+               else
+               {
+                       m_sImageName = sname;
+                       m_bmp.GetSize( sizeImage);
+                       m_ZoomCtrl.ModifyStyle( NULL, WS_BORDER, SWP_DRAWFRAME);
+                       m_TitleBar.SetText( 0, NULL, SBT_OWNERDRAW);
+               }
+
+               // Set view zoom factor and center image if no pScroll
+               SetZoomScrollSize( sizeImage, fZoom, FALSE );
+               SetScrollPage( m_sizeClient);
+               if ( CPoint( -1, -1) == pScroll)
+                       pScroll = (CPoint)(( sizeImage - m_sizeClient) / 2);
+
+               // Hide scroll bars after CZoomScrollImpl settings are complete
+               SetScrollOffset( pScroll, m_bShowScroll);
+               if ( !m_bShowScroll)
+                       ShowScrollBars( false);
+
+               // Set trackbar range and position
+               sizeImage *= 100;
+               CRect rect;
+               SystemParametersInfo( SPI_GETWORKAREA, NULL, rect, FALSE);
+               m_ZoomCtrl.SetRange( 100, max( sizeImage.cx / rect.Size().cx , sizeImage.cy / rect.Size().cy));
+               m_ZoomCtrl.SetPageSize(100);
+               m_ZoomCtrl.SetPos( (int)(100 * fZoom ));
+       }
+
+// CScrollImpl mandatory override
+       void DoPaint( CDCHandle dc)
+       {
+               if( !m_bmp.IsNull())
+                       Draw( m_bmp, dc);
+       }
+
+// Show/hide scrollbars operation
+       void ShowScrollBars( bool bShow)
+       {
+               m_bShowScroll = bShow;
+
+               if (bShow)
+               {
+                       SCROLLINFO si = { sizeof(si), SIF_PAGE | SIF_RANGE | SIF_POS};
+
+                       si.nMax = m_sizeAll.cx - 1;
+                       si.nPage = m_sizeClient.cx;
+                       si.nPos = m_ptOffset.x;
+                       SetScrollInfo(SB_HORZ, &si);
+
+                       si.nMax = m_sizeAll.cy - 1;
+                       si.nPage = m_sizeClient.cy;
+                       si.nPos = m_ptOffset.y;
+                       SetScrollInfo(SB_VERT, &si);
+               }
+               else
+               {
+                       SCROLLINFO si = { sizeof(si), SIF_RANGE, 0, 0};
+
+                       SetScrollInfo(SB_HORZ, &si);
+                       SetScrollInfo(SB_VERT, &si);
+               }
+               Invalidate();
+       }
+
+// CZoomScrollImpl::SetScrollOffset  override for hidden scrollbars
+       void SetScrollOffset( POINT ptOffset, BOOL bRedraw = TRUE )
+       {
+               if ( m_bShowScroll)
+                       CZoomScrollImpl<CImageViewView>::SetScrollOffset( ptOffset, bRedraw);
+               else
+               {
+                       m_ptOffset = CPoint( CSize( ptOffset) / m_fzoom);
+                       AdjustScrollOffset( (int&)m_ptOffset.x, (int&)m_ptOffset.y);
+                       if ( bRedraw)
+                               Invalidate();
+               }
+       }
+
+// CZoomScrollImpl::SetZoom  override for hidden scrollbars
+       void SetZoom( double fzoom, BOOL bRedraw = TRUE )
+       {
+               if ( m_bShowScroll)
+                       CZoomScrollImpl<CImageViewView>::SetZoom( fzoom, bRedraw);
+               else
+               {
+                       CPoint ptCenter = WndtoTrue( m_sizeClient / 2 );
+                       m_sizeAll = m_sizeTrue / fzoom;
+                       m_fzoom = fzoom;
+                       m_ptOffset = TruetoWnd(ptCenter) + m_ptOffset - m_sizeClient/ 2;
+                       AdjustScrollOffset( (int&)m_ptOffset.x, (int&)m_ptOffset.y);
+                       if ( bRedraw)
+                               Invalidate();
+               }
+       }
+       
+// Message map and handlers
+       BEGIN_MSG_MAP(CImageViewView)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+               MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
+               MESSAGE_RANGE_HANDLER( WM_KEYFIRST, WM_KEYLAST, OnKey)
+               CHAIN_MSG_MAP(CZoomScrollImpl<CImageViewView>)
+       ALT_MSG_MAP( 1 )        //      Forwarded by frame
+               MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnZoomColor)
+               MESSAGE_HANDLER(WM_HSCROLL, OnZoom)
+               MESSAGE_HANDLER(WM_DRAWITEM, OnDrawTitle)
+               COMMAND_ID_HANDLER(ID_VIEW_SCROLLBARS, OnShowScrollBars)
+               COMMAND_ID_HANDLER(ID_EDIT_COPY, OnCopy)
+       END_MSG_MAP()
+
+// CZoomScrollImpl::OnSize  override for hidden scrollbars
+       LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+       {
+               if ( m_bShowScroll)
+                       bHandled = FALSE;
+               else
+               {
+                       m_sizeClient = CSize( GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+                       CPoint ptOffset0 = m_ptOffset;
+                       if ( AdjustScrollOffset( (int&)m_ptOffset.x, (int&)m_ptOffset.y))
+                               ScrollWindowEx( ptOffset0.x - m_ptOffset.x, ptOffset0.y - m_ptOffset.y, m_uScrollFlags);
+               }
+               return bHandled;
+       }
+
+// Stylus interaction: tap-and-scroll and context menu
+       LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               m_ptMouse = CPoint( GET_X_LPARAM( lParam), GET_Y_LPARAM( lParam));
+               SHRGINFO shrgi = { sizeof(SHRGINFO), m_hWnd, m_ptMouse.x, m_ptMouse.y, SHRG_NOTIFYPARENT};
+               return SHRecognizeGesture( &shrgi);
+       }
+
+       LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               if ( 
+#ifdef _X86_
+                        (wParam & MK_LBUTTON) && 
+#endif // _X86_
+                        !m_bmp.IsNull())
+               {
+                       CPoint ptNew( GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+                       SetScrollOffset( GetScrollOffset() + (( m_ptMouse - ptNew) * GetZoom()));
+                       m_ptMouse = ptNew;
+               }
+               return 0;
+       }
+
+// Key translation and forwarding
+       LRESULT OnKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               switch ( wParam )
+               {
+                       case VK_UP : 
+                               wParam = VK_PRIOR;
+                               break;
+                       case VK_DOWN :
+                               wParam = VK_NEXT;
+                               break;
+               }
+               return m_ZoomCtrl.SendMessage( uMsg, wParam, lParam);
+       }
+
+////////////////////////////////////////////////////////////////
+//     ALT_MSG_MAP( 1 )  Handlers for forwarded messages
+
+//  Title bar drawing
+       LRESULT OnDrawTitle(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               CDCHandle dc = ((LPDRAWITEMSTRUCT)lParam)->hDC;
+               CRect rectTitle = ((LPDRAWITEMSTRUCT)lParam)->rcItem;
+
+               dc.FillRect( rectTitle, AtlGetStockBrush( WHITE_BRUSH));
+
+               rectTitle.DeflateRect( 2, 0);
+               dc.SetTextColor( RGB( 0, 0, 156));
+
+               CString sTitle = _T("Image: ") + m_sImageName;
+               dc.DrawText( sTitle, -1, rectTitle, DT_LEFT | DT_SINGLELINE);
+
+               sTitle.Format( _T("Zoom: %.2f"), GetZoom());
+               dc.DrawText( sTitle, -1, rectTitle, DT_RIGHT | DT_SINGLELINE);
+
+               return TRUE;
+       }
+
+//  Zoom trackbar interaction
+       LRESULT OnZoomColor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               return (LRESULT)::GetSysColorBrush( m_bmp.IsNull() ? COLOR_BTNFACE : COLOR_BTNHIGHLIGHT );
+       }
+
+       LRESULT OnZoom(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               ATLASSERT( !m_bmp.IsNull());
+               double fzoom;
+
+               switch LOWORD(wParam)
+               {
+               case SB_THUMBTRACK :
+               case SB_THUMBPOSITION :
+                       fzoom = (short int)HIWORD(wParam) / 100.0; 
+                       break;
+               default : 
+                       fzoom = m_ZoomCtrl.GetPos() / 100.0;
+               }
+
+               if ( fzoom != m_fzoom)
+               {
+                       SetZoom( fzoom);
+                       m_TitleBar.SetText( 0, NULL, SBT_OWNERDRAW);
+               }
+               return TRUE;
+       }
+
+//  Scroll bars show-hide
+       LRESULT OnShowScrollBars(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ShowScrollBars( !m_bShowScroll);
+               return TRUE;
+       }
+
+//  Clipboard copy 
+       LRESULT OnCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               if ( !AtlSetClipboardDib16( m_bmp , m_sizeAll, m_hWnd))
+                       AtlMessageBox( m_hWnd, L"Could not copy image to clipboard", IDR_MAINFRAME, MB_OK | MB_ICONWARNING);
+               return 0;
+       }
+};
+
+#endif // !defined(_IMAGEVIEW_VIEW_H__)
diff --git a/include/WTL/Samples/ImageView/mainfrm.h b/include/WTL/Samples/ImageView/mainfrm.h
new file mode 100644 (file)
index 0000000..064b339
--- /dev/null
@@ -0,0 +1,386 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#if !defined(_IMAGEVIEW_MAINFRM_H_)
+#define _IMAGEVIEW_MAINFRM_H_
+
+
+// Selective message forwarding macros
+
+#define FORWARD_MSG(msg) if ( uMsg == msg ) \
+       { lResult = ::SendMessage( GetParent(), uMsg, wParam, lParam ); return bHandled = TRUE;}
+
+#define FORWARD_NOTIFICATION_ID(uID) if (( uMsg == WM_NOTIFY) && ( wParam == uID)) \
+       { lResult = ::SendMessage( GetParent(), uMsg, wParam, lParam ); return bHandled = TRUE;}
+
+
+/////////////////////
+// CMainFrame : Application main window
+
+typedef CWinTraits< WS_CLIPCHILDREN | WS_CLIPSIBLINGS ,0> CCeFrameTraits;
+
+class CMainFrame : 
+               public CFrameWindowImpl<CMainFrame,CWindow,CCeFrameTraits>, 
+               public CUpdateUI<CMainFrame>,
+               public CMessageFilter, public CIdleHandler, 
+               public CFullScreenFrame<CMainFrame, false>,
+               public CAppWindow<CMainFrame>
+{
+
+// CZoomMenuBar: MenuBar forwarding trackbar messages
+       class CZoomMenuBar : public CWindowImpl< CZoomMenuBar, CMenuBarCtrl >
+       {
+       public:
+               DECLARE_WND_SUPERCLASS( L"ZoomMenuBar", L"ToolbarWindow32");
+
+               BEGIN_MSG_MAP(CZoomMenuBar)
+                       FORWARD_MSG(WM_HSCROLL)
+                       FORWARD_MSG(WM_CTLCOLORSTATIC)
+                       FORWARD_NOTIFICATION_ID(ID_ZOOM)
+               END_MSG_MAP()
+       };
+
+// Data and declarations
+public:
+       typedef CFrameWindowImpl<CMainFrame,CWindow,CCeFrameTraits> BaseFrame;
+       typedef CFullScreenFrame<CMainFrame, false> BaseFullScreen;
+
+       DECLARE_APP_FRAME_CLASS(NULL, IDR_MAINFRAME, L"Software\\WTL\\ImageView")
+       CImageViewView m_view;
+       CString m_sFile;
+       CZoomMenuBar m_MenuBar;
+
+// CMessageFilter pure virtual definition
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if( BaseFrame::PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return m_view.PreTranslateMessage(pMsg);
+       }
+
+
+// CFrameWindowImplBase::UpdateLayout override for CCS_TOP status bar
+       void UpdateLayout(BOOL bResizeBars = TRUE)
+       {
+               CRect rectWnd, rectTool;
+               GetClientRect( rectWnd);
+
+               // resize title bar
+               if( m_view.m_TitleBar.IsWindow() && ( m_view.m_TitleBar.GetStyle() & WS_VISIBLE))
+               {
+                       if(bResizeBars)
+                               m_view.m_TitleBar.SendMessage( WM_SIZE);
+                       m_view.m_TitleBar.GetWindowRect( rectTool);
+                       rectWnd.top += rectTool.Size().cy;
+               }
+
+               // resize view
+               if ( m_view.IsWindow())
+               {
+                       m_view.GetWindowRect( rectTool);
+                       if ( rectTool != rectWnd)
+                               m_view.SetWindowPos( NULL, rectWnd, SWP_NOZORDER | SWP_NOACTIVATE);
+               }
+       }
+
+// CAppWindow operations
+       bool AppHibernate( bool bHibernate)
+       {
+               if ( bHibernate)        // go to sleep
+                       if ( m_sFile.IsEmpty()) // clipboard or no image
+                               return false;
+                       else
+                               m_view.m_bmp.DeleteObject();
+               
+               else    // wake up 
+                       if ( HBITMAP hbm = LoadImageFile( m_sFile))
+                               m_view.m_bmp.Attach( hbm);
+                       else    // file was moved or deleted during hibernation
+                               CloseImage();
+
+               return bHibernate;
+       }
+
+       bool AppNewInstance( LPCTSTR lpstrCmdLine)
+       {
+               return SetImageFile( lpstrCmdLine) != NULL;
+       }
+
+       void AppSave()
+       {
+               CAppInfo info;
+               BOOL bTitle = m_view.m_TitleBar.IsWindowVisible();
+               info.Save( bTitle, L"TitleBar");
+               info.Save( m_view.m_bShowScroll, L"ScrollBars");
+               info.Save( m_bFullScreen, L"Full");
+               info.Save( m_sFile, L"Image");
+               info.Save( m_view.GetScrollOffset(), L"Scroll");
+               info.Save( m_view.m_fzoom, L"Zoom");
+       }
+
+// File and image operations
+       HBITMAP LoadImageFile( LPCTSTR szFileName )
+       {
+               CString szImage = szFileName;
+               CBitmapHandle hBmp = szImage.Find( L".bmp") != -1 ? 
+                       ::SHLoadDIBitmap( szFileName) : ::SHLoadImageFile( szFileName);
+
+               if( hBmp.IsNull())
+               {
+                       CString strMsg = L"Cannot load image from: ";
+                       strMsg += szFileName;
+                       AtlMessageBox( m_hWnd, (LPCTSTR)strMsg, IDR_MAINFRAME, MB_OK | MB_ICONERROR);
+               }
+               return hBmp;
+       }
+       
+       bool SetImageFile( LPCTSTR szFileName, double fZoom = 1.0 , POINT ptScroll= CPoint( -1, -1))
+       {
+               CBitmapHandle hBmp;
+               if ( szFileName && *szFileName)
+                       hBmp = LoadImageFile( szFileName);
+               bool bOK = !hBmp.IsNull();
+               if( bOK)
+               {
+                       m_sFile = szFileName;
+                       CString sImageName = m_sFile.Mid( m_sFile.ReverseFind(L'\\') + 1);
+                       m_view.SetImage( hBmp, sImageName.Left( sImageName.ReverseFind(L'.')), fZoom, ptScroll );
+               }
+               else
+                       CloseImage();
+
+               UIEnable(ID_ZOOM, bOK);
+               UIEnable(ID_FILE_CLOSE, bOK);
+               UIEnable(ID_EDIT_COPY, bOK);
+               UIEnable(ID_VIEW_PROPERTIES, bOK);
+               return bOK;
+       }
+
+       void CloseImage()
+       {
+               m_sFile.Empty();
+               m_view.SetImage( NULL);
+       }
+
+// UpdateUI operations and map
+       virtual BOOL OnIdle()
+       {
+               UIEnable( ID_EDIT_PASTE, IsClipboardFormatAvailable( CF_DIB));
+               UIUpdateToolBar();
+               UIUpdateChildWindows();
+               return FALSE;
+       }
+
+       BEGIN_UPDATE_UI_MAP(CMainFrame)
+               UPDATE_ELEMENT(ID_EDIT_COPY, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_PASTE, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_FILE_CLOSE, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_VIEW_PROPERTIES, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_SCROLLBARS, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_ZOOM, UPDUI_CHILDWINDOW)
+       END_UPDATE_UI_MAP()
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CMainFrame)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               NOTIFY_CODE_HANDLER(GN_CONTEXTMENU, OnContextMenu)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnExit)
+               COMMAND_ID_HANDLER(ID_FILE_OPEN, OnFileOpen)
+               COMMAND_ID_HANDLER(ID_FILE_CLOSE, OnFileClose)
+               COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnPaste)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_ID_HANDLER(ID_FILE_REGISTER, OnRegister)
+               COMMAND_ID_HANDLER(ID_VIEW_PROPERTIES, OnProperties)
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnTitle)
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnFullScreen)
+               COMMAND_ID_HANDLER(ID_VIEW_SCROLLBARS, OnScrollBars)
+               CHAIN_MSG_MAP(BaseFullScreen)
+               CHAIN_MSG_MAP(CAppWindow<CMainFrame>)
+               CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
+               CHAIN_MSG_MAP(BaseFrame)
+               CHAIN_MSG_MAP_ALT_MEMBER(m_view, 1)
+       END_MSG_MAP()
+
+// Creation and destruction
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               CAppInfo info;
+
+               // Full screen delayed restoration 
+               bool bFull = false;
+               info.Restore( bFull, L"Full");
+               if ( bFull)
+                       PostMessage( WM_COMMAND, ID_VIEW_TOOLBAR);
+
+               // MenuBar creation
+               CreateSimpleCEMenuBar( IDR_MAINFRAME, SHCMBF_HIDESIPBUTTON);
+               m_MenuBar.SubclassWindow( m_hWndCECommandBar);
+               m_MenuBar.LoadStdImages( IDB_STD_SMALL_COLOR);
+               UIAddToolBar( m_hWndCECommandBar);
+
+               // Trackbar creation
+               CRect rZoom;
+               m_MenuBar.GetRect( ID_ZOOM, rZoom);
+               rZoom.top -= 1;
+               m_view.m_ZoomCtrl.Create( m_hWndCECommandBar, rZoom, NULL ,WS_CHILD | TBS_TOP | TBS_FIXEDLENGTH, 0, 
+                       ID_ZOOM );
+               m_view.m_ZoomCtrl.SetThumbLength( 9); 
+               rZoom.DeflateRect( 1, 1);
+               m_view.m_ZoomCtrl.SetWindowPos( HWND_TOP, rZoom.left, rZoom.top + 1, 
+                       rZoom.Width(), rZoom.Height(), SWP_SHOWWINDOW); 
+               UIAddChildWindowContainer( m_hWndCECommandBar);
+
+               // TitleBar creation
+               BOOL bTitle = TRUE;
+               info.Restore( bTitle, L"TitleBar");
+               DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_TOP;
+               if ( bTitle)
+                       dwStyle |= WS_VISIBLE;
+               CreateSimpleStatusBar( L"", dwStyle);
+               m_view.m_TitleBar.Attach( m_hWndStatusBar);
+               UISetCheck( ID_VIEW_STATUS_BAR, bTitle);
+
+               // View creation
+               info.Restore( m_view.m_bShowScroll, L"ScrollBars");
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+               UISetCheck( ID_VIEW_SCROLLBARS, m_view.m_bShowScroll);
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               // Image initialization
+               LPCTSTR pCmdLine = (LPCTSTR)((LPCREATESTRUCT)lParam)->lpCreateParams;
+               if ( *pCmdLine )// open the command line file
+                       SetImageFile( pCmdLine);
+               else                    // restore previous image if existing
+               {
+                       CPoint ptScroll( 0, 0);
+                       double fzoom = 1.;
+                       info.Restore( m_sFile, L"Image");
+                       if ( !m_sFile.IsEmpty())
+                       {
+                               info.Restore( ptScroll, L"Scroll");
+                               info.Restore( fzoom, L"Zoom");
+                       }
+                       SetImageFile( m_sFile, fzoom, ptScroll);
+               }
+               return 0;
+       }
+
+       LRESULT OnExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+
+// File and image transfers
+       LRESULT OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               LPCTSTR sFiles = 
+                       L"Image Files\0*.bmp;*.jpg;*.gif;*.png\0"
+                       L"Bitmap Files (*.bmp)\0*.bmp\0"
+                       L"JPEG Files (*.jpg)\0*.jpg\0"
+                       L"PNG Files (*.png)\0*.png\0"
+                       L"GIF Files (*.gif)\0*.gif\0"
+                       L"All Files (*.*)\0*.*\0\0";
+
+               CFileDialog dlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, sFiles);
+
+               if( FSDoModal( dlg) == IDOK)
+                       SetImageFile( dlg.m_szFileName);
+
+               return 0;
+       }
+
+       LRESULT OnFileClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               SetImageFile( NULL);
+               return NULL;
+       }
+
+       LRESULT OnPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               if ( CBitmapHandle hbm = AtlGetClipboardDib( m_hWnd))
+               {
+                       m_sFile.Empty();
+                       m_view.SetImage( hbm, L"pasted");
+                       UIEnable(ID_ZOOM, true);
+                       UIEnable(ID_FILE_CLOSE, true);
+                       UIEnable(ID_EDIT_COPY, true);
+                       UIEnable(ID_VIEW_PROPERTIES, true);
+               }
+               else
+                       AtlMessageBox( m_hWnd, L"Could not paste image from clipboard", IDR_MAINFRAME, MB_OK | MB_ICONERROR);
+               return 0;
+       }
+
+// Dialogs and property sheet activation
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+#ifdef _WTL_CE_DRA
+               CStdSimpleOrientedDialog<IDD_ABOUTBOX, IDD_ABOUTBOX_L, SHIDIF_DONEBUTTON | SHIDIF_FULLSCREENNOMENUBAR> dlg;
+#else
+               CAboutDlg dlg;
+#endif
+               return FSDoModal( dlg);
+       }
+
+       LRESULT OnRegister(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CRegisterDlg dlg;
+               return FSDoModal( dlg);
+       }
+
+       LRESULT OnProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CImageProperties prop( m_sFile, m_view);
+               return FSDoModal( prop);
+       }
+
+// User interface settings
+       LRESULT OnTitle(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bView = !m_view.m_TitleBar.IsWindowVisible();
+               m_view.m_TitleBar.ShowWindow( bView ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UpdateLayout();
+               UISetCheck( ID_VIEW_STATUS_BAR, bView);
+               return TRUE;
+       }
+
+       LRESULT OnFullScreen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               SetFullScreen( !m_bFullScreen );
+               UISetCheck( ID_VIEW_TOOLBAR, m_bFullScreen);
+               return TRUE;
+       }
+
+       LRESULT OnScrollBars(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled)
+       {
+               UISetCheck( ID_VIEW_SCROLLBARS, !m_view.m_bShowScroll);
+               return bHandled = FALSE; // real processing is in m_view
+       }
+
+       LRESULT OnContextMenu(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               PNMRGINFO pnmrgi = (PNMRGINFO)pnmh ;
+               CMenuHandle menu;
+               menu.LoadMenu( IDR_POPUP);
+               menu = menu.GetSubMenu( 0);
+               return menu.TrackPopupMenu( TPM_CENTERALIGN | TPM_VERTICAL, 
+                       pnmrgi->ptAction.x, pnmrgi->ptAction.y, m_hWnd);
+       }
+       
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // !defined(_IMAGEVIEW_MAINFRM_H_)
diff --git a/include/WTL/Samples/ImageView/res/BmpView.ico b/include/WTL/Samples/ImageView/res/BmpView.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/Samples/ImageView/res/BmpView.ico differ
diff --git a/include/WTL/Samples/ImageView/res/bitmap1.bmp b/include/WTL/Samples/ImageView/res/bitmap1.bmp
new file mode 100644 (file)
index 0000000..336c0c6
Binary files /dev/null and b/include/WTL/Samples/ImageView/res/bitmap1.bmp differ
diff --git a/include/WTL/Samples/ImageView/res/bitmap2.bmp b/include/WTL/Samples/ImageView/res/bitmap2.bmp
new file mode 100644 (file)
index 0000000..489a025
Binary files /dev/null and b/include/WTL/Samples/ImageView/res/bitmap2.bmp differ
diff --git a/include/WTL/Samples/ImageView/resource.h b/include/WTL/Samples/ImageView/resource.h
new file mode 100644 (file)
index 0000000..ac73f46
--- /dev/null
@@ -0,0 +1,80 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by ImageView.VS.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDR_POPUP                       202
+#define IDD_PROP_FILE                   202
+#define IDD_PROP_IMAGE                  203
+#define IDR_MAINFRAME256                203
+#define IDR_MAINFRAME0                  204
+#define IDD_REGISTER                    205
+#define IDR_MAINFRAME1                  205
+#define IDD_MOVE                        206
+#define IDD_PROP_VIEW                   208
+#define IDB_BITMAP1                     208
+#define IDB_BITMAP2                     209
+#define IDD_REGISTER_L                  215
+#define IDD_ABOUTBOX_L                  216
+#define IDC_IMAGE                       1000
+#define IDC_BMP                         1000
+#define IDC_JPG                         1001
+#define IDC_PNG                         1002
+#define IDC_GIF                         1003
+#define IDC_MOVE                        1004
+#define IDC_TEXT                        1005
+#define IDC_SHORTCUT                    1006
+#define IDC_FILEICON                    1007
+#define IDC_TYPENAME                    1008
+#define IDC_FILELOCATION                1009
+#define IDC_FILESIZE                    1010
+#define IDC_FILEDATE                    1011
+#define IDC_FILEATTRIB                  1012
+#define IDC_IBMP                        1012
+#define IDC_IJPG                        1013
+#define IDC_FILENAME                    1013
+#define IDC_IPNG                        1014
+#define IDC_IGIF                        1015
+#define IDC_NUMCOLORS                   1015
+#define IDC_BITDEPTH                    1016
+#define IDC_IMAGESIZE                   1018
+#define IDC_NUMBYTES                    1020
+#define IDC_ZOOM                        1021
+#define IDC_VIEW                        1022
+#define IDC_FILELOCATION_H              1023
+#define IDC_MOVE_T                      1024
+#define IDC_TYPENAME_H                  1030
+#define IDC_FILENAME_H                  1031
+#define IDC_FILESIZE_H                  1032
+#define IDC_FILEDATE_H                  1033
+#define IDC_FILEATTRIB_H                1034
+#define IDC_IMAGESIZE_H                 1035
+#define IDC_NUMCOLORS_H                 1036
+#define IDC_BITDEPTH_H                  1037
+#define IDC_NUMBYTES_H                  1038
+#define IDC_HEAD                        1039
+#define IDC_APPICON                     1040
+#define IDC_LICENSE                     1041
+#define IDC_REGISTER_H                  1042
+#define ID_ZOOM                         32773
+#define ID_VIEW_PROPERTIES              32774
+#define IDS_CAP_FILE                    32777
+#define IDS_CAP_HELP                    32783
+#define IDS_CAP_ZOOMTRACK               32785
+#define IDS_CAP_VIEW                    32788
+#define ID_MENU                         32790
+#define IDS_CAP_MENU                    32792
+#define ID_VIEW_SCROLLBARS              32802
+#define ID_FILE_REGISTER                32807
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        217
+#define _APS_NEXT_COMMAND_VALUE         32820
+#define _APS_NEXT_CONTROL_VALUE         1043
+#define _APS_NEXT_SYMED_VALUE           104
+#endif
+#endif
diff --git a/include/WTL/Samples/ImageView/stdafx.cpp b/include/WTL/Samples/ImageView/stdafx.cpp
new file mode 100644 (file)
index 0000000..efbf77b
--- /dev/null
@@ -0,0 +1,6 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     ImageView.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
diff --git a/include/WTL/Samples/ImageView/stdafx.h b/include/WTL/Samples/ImageView/stdafx.h
new file mode 100644 (file)
index 0000000..f163910
--- /dev/null
@@ -0,0 +1,24 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+// Change these values to use different versions
+#define WINVER         0x0420
+
+#define _WIN32_WCE_AYGSHELL 1
+
+#include <atlbase.h>
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#if defined( DEBUG) && !defined( _DEBUG)
+       #define _DEBUG
+#endif
+
+#include <atlwin.h>
+
+#include <aygshell.h>
+#pragma comment(lib, "aygshell.lib")
+
diff --git a/include/WTL/Samples/MDIDocVw/HELLO.ICO b/include/WTL/Samples/MDIDocVw/HELLO.ICO
new file mode 100644 (file)
index 0000000..d46461a
Binary files /dev/null and b/include/WTL/Samples/MDIDocVw/HELLO.ICO differ
diff --git a/include/WTL/Samples/MDIDocVw/MDI.ICO b/include/WTL/Samples/MDIDocVw/MDI.ICO
new file mode 100644 (file)
index 0000000..52982ee
Binary files /dev/null and b/include/WTL/Samples/MDIDocVw/MDI.ICO differ
diff --git a/include/WTL/Samples/MDIDocVw/MDI.cpp b/include/WTL/Samples/MDIDocVw/MDI.cpp
new file mode 100644 (file)
index 0000000..9ffb79d
--- /dev/null
@@ -0,0 +1,42 @@
+#include "stdafx.h"
+
+#include <atlframe.h>
+#include <atlgdi.h>
+#include <atldlgs.h>
+
+#include "resource.h"
+#include "mainfrm.h"
+
+CAppModule _Module;
+
+int Run(LPSTR lpCmdLine = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       CMDIFrame wndMain;
+
+       if(wndMain.CreateEx() == NULL)
+       {
+               ATLTRACE(_T("Main window creation failed!\n"));
+               return 0;
+       }
+
+       wndMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR lpCmdLine, int nCmdShow)
+{
+       ::InitCommonControls();
+       _Module.Init(NULL, hInstance);
+
+       int nRet = Run(lpCmdLine, nCmdShow);
+
+       _Module.Term();
+       return nRet;
+}
diff --git a/include/WTL/Samples/MDIDocVw/MDI.sln b/include/WTL/Samples/MDIDocVw/MDI.sln
new file mode 100644 (file)
index 0000000..dcb981b
--- /dev/null
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MDI", "MDI.vcproj", "{53581F92-A24A-480E-9B60-ABA01A256FEB}"
+EndProject
+Global
+       GlobalSection(SolutionConfiguration) = preSolution
+               ConfigName.0 = Debug
+               ConfigName.1 = Release
+       EndGlobalSection
+       GlobalSection(ProjectDependencies) = postSolution
+       EndGlobalSection
+       GlobalSection(ProjectConfiguration) = postSolution
+               {53581F92-A24A-480E-9B60-ABA01A256FEB}.Debug.ActiveCfg = Debug|Win32
+               {53581F92-A24A-480E-9B60-ABA01A256FEB}.Debug.Build.0 = Debug|Win32
+               {53581F92-A24A-480E-9B60-ABA01A256FEB}.Release.ActiveCfg = Release|Win32
+               {53581F92-A24A-480E-9B60-ABA01A256FEB}.Release.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+       EndGlobalSection
+       GlobalSection(ExtensibilityAddIns) = postSolution
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/MDIDocVw/mainfrm.h b/include/WTL/Samples/MDIDocVw/mainfrm.h
new file mode 100644 (file)
index 0000000..5a5bdae
--- /dev/null
@@ -0,0 +1,815 @@
+#include <atlctrls.h>
+#include <atlctrlw.h>
+
+class CHelloView : public CWindowImpl<CHelloView>
+{
+public:
+       COLORREF m_clrText;
+
+       //state of color buttons
+       BOOL m_bBlack;
+       BOOL m_bRed;
+       BOOL m_bBlue;
+       BOOL m_bGreen;
+       BOOL m_bWhite;
+       BOOL m_bCustom;
+
+       CUpdateUIBase* m_pUpdateUI;
+
+       CHelloView(CUpdateUIBase* pUpdateUI) : m_clrText(RGB(0, 0, 0)),
+               m_bBlack(TRUE),
+               m_bRed(FALSE),
+               m_bBlue(FALSE),
+               m_bGreen(FALSE),
+               m_bWhite(FALSE),
+               m_bCustom(FALSE),
+               m_pUpdateUI(pUpdateUI)
+       { }
+
+       DECLARE_WND_CLASS(NULL)
+
+       void ClearAllColors()
+       {
+               m_bBlack = m_bBlue = m_bRed = FALSE;
+               m_bWhite = m_bGreen = FALSE;
+       }
+
+       void MixColors() 
+       {
+               COLORREF tmpClr;
+               int r, g, b;
+               BOOL bSetColor;
+               
+               // Determine which colors are currently chosen.
+               bSetColor = m_bRed || m_bGreen || m_bBlue || m_bWhite || m_bBlack;
+
+               // If the current color is custom, ignore mix request.
+               if(!bSetColor && m_bCustom)
+                       return;
+
+               // Set color value to black and then add the necessary colors.
+               r = g = b = 0;
+
+               if(m_bRed)
+                       r = 255;
+               if(m_bGreen)
+                       g = 255;
+               if(m_bBlue)
+                       b = 255;
+
+               tmpClr = RGB(r, g, b);
+
+       // NOTE: Because a simple algorithm is used to mix colors
+       // if the current selection contains black or white, the 
+       // result will be black or white; respectively. This is due
+       // to the additive method for mixing the colors.
+
+               if(m_bBlack)
+                       tmpClr = RGB(0, 0, 0);
+
+               if(m_bWhite)
+                       tmpClr = RGB(255, 255, 255);
+
+               // Once the color has been determined, update document 
+               // data, and force repaint of all views.
+
+               if(!bSetColor)
+                       m_bBlack = TRUE;
+               m_clrText = tmpClr;
+               m_bCustom = FALSE;
+
+               UpdateButtons();
+               Invalidate();
+       }
+
+       void UpdateButtons()
+       {
+               m_pUpdateUI->UISetCheck(ID_BLACK, m_bBlack);
+               m_pUpdateUI->UISetCheck(ID_RED, m_bRed);
+               m_pUpdateUI->UISetCheck(ID_GREEN, m_bGreen);
+               m_pUpdateUI->UISetCheck(ID_BLUE, m_bBlue);
+               m_pUpdateUI->UISetCheck(ID_WHITE, m_bWhite);
+               m_pUpdateUI->UISetCheck(ID_CUSTOM, m_bCustom);
+       }
+
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+
+       BEGIN_MSG_MAP(CHelloView)
+               MESSAGE_HANDLER(WM_PAINT, OnPaint)
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+               COMMAND_RANGE_HANDLER(ID_BLACK, ID_WHITE, OnColor)
+               COMMAND_ID_HANDLER(ID_CUSTOM, OnCustomColor)
+       END_MSG_MAP()
+
+       LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&)
+       {
+               CPaintDC dc(m_hWnd);
+
+               RECT rect;
+               GetClientRect(&rect);
+               dc.SetTextColor(m_clrText);
+               dc.SetBkColor(::GetSysColor(COLOR_WINDOW));
+               dc.DrawText(_T("Hello, ATL"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+
+               return 0;
+       }
+
+       LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               m_pUpdateUI->UIEnable(ID_BLACK, TRUE);
+               m_pUpdateUI->UIEnable(ID_RED, TRUE);
+               m_pUpdateUI->UIEnable(ID_GREEN, TRUE);
+               m_pUpdateUI->UIEnable(ID_BLUE, TRUE);
+               m_pUpdateUI->UIEnable(ID_WHITE, TRUE);
+               m_pUpdateUI->UIEnable(ID_CUSTOM, TRUE);
+
+               m_pUpdateUI->UISetCheck(ID_SPEED_SLOW, 0);
+               m_pUpdateUI->UISetCheck(ID_SPEED_FAST, 0);
+               m_pUpdateUI->UIEnable(ID_SPEED_SLOW, FALSE);
+               m_pUpdateUI->UIEnable(ID_SPEED_FAST, FALSE);
+
+               UpdateButtons();
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnColor(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               switch(wID)
+               {
+                case ID_BLACK:
+                       ClearAllColors();
+                       m_bBlack = !(m_bBlack);
+                       break;
+                case ID_WHITE:
+                       ClearAllColors();
+                       m_bWhite = !(m_bWhite);
+                       break;
+                case ID_RED:
+                       m_bRed = !(m_bRed);
+                       m_bBlack = FALSE;
+                       m_bWhite = FALSE;
+                       break;
+                case ID_GREEN:
+                       m_bGreen = !(m_bGreen);
+                       m_bBlack = FALSE;
+                       m_bWhite = FALSE;
+                       break;
+                case ID_BLUE:
+                       m_bBlue = !(m_bBlue);
+                       m_bBlack = FALSE;
+                       m_bWhite = FALSE;
+                       break;
+                default:
+                       TCHAR buff[256];
+                       ::LoadString(_Module.GetResourceInstance(), IDS_UNKCOLOR, buff, 255);
+                       MessageBox(buff);
+                       return 1;
+               }
+               MixColors();
+               return 0;
+       }
+
+       LRESULT OnCustomColor(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               CColorDialog dlgColor(m_clrText);
+               if(dlgColor.DoModal() == IDOK)
+               {
+                       m_clrText = dlgColor.GetColor();
+                       ClearAllColors();
+                       m_bCustom = TRUE;
+                       UpdateButtons();
+                       Invalidate();
+               }
+               return 0;
+       }
+};
+
+class CHelloWnd : public CMDIChildWindowImpl<CHelloWnd>
+{
+public:
+       CHelloView* m_pView;
+       CUpdateUIBase* m_pUpdateUI;
+
+       CHelloWnd(CUpdateUIBase* pUpdateUI) : m_pView(NULL), m_pUpdateUI(pUpdateUI)
+       { }
+
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_HELLOTYPE)
+
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+
+       BEGIN_MSG_MAP(CHelloWnd)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               CHAIN_CLIENT_COMMANDS()
+               CHAIN_MSG_MAP(CMDIChildWindowImpl<CHelloWnd>)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT, WPARAM, LPARAM lParam, BOOL& bHandled)
+       {
+               m_pView = new CHelloView(m_pUpdateUI);
+               RECT rect = { 0, 0, 1, 1 };
+               m_hWndClient = m_pView->Create(m_hWnd, rect, NULL, WS_CHILD | WS_VISIBLE, WS_EX_CLIENTEDGE);
+
+               bHandled = FALSE;
+               return 1;
+       }
+};
+
+
+#define ABS(x) ((x) < 0? -(x) : (x) > 0? (x) : 0)
+
+class CBounceView : public CWindowImpl<CBounceView>
+{
+public:
+       COLORREF m_clrBall;
+
+       //state of color buttons
+       BOOL m_bBlack;
+       BOOL m_bRed;
+       BOOL m_bBlue;
+       BOOL m_bGreen;
+       BOOL m_bWhite;
+       BOOL m_bCustom;
+
+       BOOL m_bFastSpeed;         // current speed
+
+       POINT m_ptPixel;           // pixel size
+       SIZE m_sizeRadius;         // radius of ball
+       SIZE m_sizeMove;           // move speed
+       SIZE m_sizeTotal;          // total size for ball bitmap
+       POINT m_ptCenter;          // current center for the ball
+
+       CBitmap m_bmBall;          // for replicating bouncing ball
+
+       CUpdateUIBase* m_pUpdateUI;
+
+       CBounceView(CUpdateUIBase* pUpdateUI) : m_clrBall(RGB(0, 0, 0)),
+               m_bBlack(TRUE),
+               m_bRed(FALSE),
+               m_bBlue(FALSE),
+               m_bGreen(FALSE),
+               m_bWhite(FALSE),
+               m_bCustom(FALSE),
+               m_bFastSpeed(FALSE), m_pUpdateUI(pUpdateUI)
+       { }
+
+       DECLARE_WND_CLASS(NULL)
+
+       HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       UINT nID = 0, LPVOID lpCreateParam = NULL)
+       {
+               CWndClassInfo& wci = GetWndClassInfo();
+               wci.m_lpszCursorID = IDC_SIZENS;
+               ATOM atom = wci.Register(&m_pfnSuperWindowProc);
+               return CWindowImplBase::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle,
+                       nID, atom);
+       }
+
+       void ClearAllColors()
+       {
+               m_bBlack = m_bBlue = m_bRed = FALSE;
+               m_bWhite = m_bGreen = FALSE;
+       }
+
+       void MixColors() 
+       {
+               COLORREF tmpClr;
+               int r, g, b;
+               BOOL bSetColor;
+               
+               // Determine which colors are currently chosen.
+               bSetColor = m_bRed || m_bGreen || m_bBlue || m_bWhite || m_bBlack;
+
+               // If the current color is custom, ignore mix request.
+               if(!bSetColor && m_bCustom)
+                       return;
+
+               // Set color value to black and then add the necessary colors.
+               r = g = b = 0;
+
+               if(m_bRed)
+                       r = 255;
+               if(m_bGreen)
+                       g = 255;
+               if(m_bBlue)
+                       b = 255;
+
+               tmpClr = RGB(r, g, b);
+
+       // NOTE: Because a simple algorithm is used to mix colors
+       // if the current selection contains black or white, the 
+       // result will be black or white; respectively. This is due
+       // to the additive method for mixing the colors.
+
+               if(m_bBlack)
+                       tmpClr = RGB(0, 0, 0);
+
+               if(m_bWhite)
+                       tmpClr = RGB(255, 255, 255);
+
+               // Once the color has been determined, update document 
+               // data, and force repaint of all views.
+
+               if(!bSetColor)
+                       m_bBlack = TRUE;
+               m_clrBall = tmpClr;
+               m_bCustom = FALSE;
+
+               UpdateColorButtons();
+               MakeNewBall();
+               Invalidate();
+       }
+
+       void UpdateColorButtons()
+       {
+               m_pUpdateUI->UISetCheck(ID_BLACK, m_bBlack);
+               m_pUpdateUI->UISetCheck(ID_RED, m_bRed);
+               m_pUpdateUI->UISetCheck(ID_GREEN, m_bGreen);
+               m_pUpdateUI->UISetCheck(ID_BLUE, m_bBlue);
+               m_pUpdateUI->UISetCheck(ID_WHITE, m_bWhite);
+               m_pUpdateUI->UISetCheck(ID_CUSTOM, m_bCustom);
+       }
+
+       void UpdateSpeedButtons()
+       {
+               m_pUpdateUI->UISetCheck(ID_SPEED_SLOW, !m_bFastSpeed);
+               m_pUpdateUI->UISetCheck(ID_SPEED_FAST, m_bFastSpeed);
+       }
+
+       void MakeNewBall()
+       {
+               m_sizeTotal.cx = (m_sizeRadius.cx + ABS(m_sizeMove.cx)) << 1;
+               m_sizeTotal.cy = (m_sizeRadius.cy + ABS(m_sizeMove.cy)) << 1;
+
+               if(m_bmBall.m_hBitmap != NULL)
+                       m_bmBall.DeleteObject();        // get rid of old bitmap
+
+               CClientDC dc(m_hWnd);
+               CDC dcMem;
+               dcMem.CreateCompatibleDC(dc);
+
+               m_bmBall.CreateCompatibleBitmap(dc, m_sizeTotal.cx, m_sizeTotal.cy);
+               _ASSERTE(m_bmBall.m_hBitmap != NULL);
+
+               dcMem.SelectBitmap(m_bmBall);
+
+               // draw a rectangle in the background (window) color
+               RECT rect = { 0, 0, m_sizeTotal.cx, m_sizeTotal.cy };
+               CBrush brBackground;
+               brBackground.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
+               dcMem.FillRect(&rect, brBackground);
+
+               CBrush brCross;
+               brCross.CreateHatchBrush(HS_DIAGCROSS, 0L);
+               dcMem.SelectBrush(brCross);
+
+               dcMem.SetBkColor(m_clrBall);
+               dcMem.Ellipse(ABS(m_sizeMove.cx), ABS(m_sizeMove.cy),
+                       m_sizeTotal.cx - ABS(m_sizeMove.cx),
+                       m_sizeTotal.cy - ABS(m_sizeMove.cy));
+       }
+
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+
+       BEGIN_MSG_MAP(CBounceView)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+               MESSAGE_HANDLER(WM_SIZE, OnSize)
+               MESSAGE_HANDLER(WM_TIMER, OnTimer)
+               COMMAND_RANGE_HANDLER(ID_BLACK, ID_WHITE, OnColor)
+               COMMAND_ID_HANDLER(ID_CUSTOM, OnCustomColor)
+               COMMAND_ID_HANDLER(ID_SPEED_SLOW, OnChangeSpeed)
+               COMMAND_ID_HANDLER(ID_SPEED_FAST, OnChangeSpeed)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL& bHandled)
+       {
+#if (_ATL_VER >= 0x0300)
+               if(!SetTimer(1, 100))   // start slow
+#else
+               if(!SetTimer(1, 100, NULL))     // start slow
+#endif //(_ATL_VER == 0x0300)
+               {
+                       MessageBox(_T("Not enough timers available for this window."),
+                                       _T("MDI:Bounce"), MB_ICONEXCLAMATION | MB_OK);
+
+                       // signal creation failure...
+                       return -1;
+               }
+
+               CClientDC dc(m_hWnd);
+               m_ptPixel.x = dc.GetDeviceCaps(ASPECTX);
+               m_ptPixel.y = dc.GetDeviceCaps(ASPECTY);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               m_pUpdateUI->UIEnable(ID_BLACK, TRUE);
+               m_pUpdateUI->UIEnable(ID_RED, TRUE);
+               m_pUpdateUI->UIEnable(ID_GREEN, TRUE);
+               m_pUpdateUI->UIEnable(ID_BLUE, TRUE);
+               m_pUpdateUI->UIEnable(ID_WHITE, TRUE);
+               m_pUpdateUI->UIEnable(ID_CUSTOM, TRUE);
+               m_pUpdateUI->UIEnable(ID_SPEED_SLOW, TRUE);
+               m_pUpdateUI->UIEnable(ID_SPEED_FAST, TRUE);
+
+               UpdateColorButtons();
+               UpdateSpeedButtons();
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               int cx = LOWORD(lParam);
+               int cy = HIWORD(lParam);
+               LONG lScale;
+
+               m_ptCenter.x = cx >> 1;
+               m_ptCenter.y = cy >> 1;
+               m_ptCenter.x += cx >> 3; // make the ball a little off-center
+
+               lScale = min((LONG)cx * m_ptPixel.x,
+                       (LONG)cy * m_ptPixel.y) >> 4;
+               m_sizeRadius.cx = (int)(lScale / m_ptPixel.x);
+               m_sizeRadius.cy = (int)(lScale / m_ptPixel.y);
+               m_sizeMove.cx = max(1, m_sizeRadius.cy >> 2);
+               m_sizeMove.cy = max(1, m_sizeRadius.cy >> 2);
+
+               MakeNewBall();
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnTimer(UINT, WPARAM, LPARAM, BOOL& bHandled)
+       {
+               if (m_bmBall.m_hBitmap == NULL)
+                       return 1;     // no bitmap for the ball
+
+               RECT rcClient;
+               GetClientRect(&rcClient);
+
+               CClientDC dc(m_hWnd);
+
+               CDC dcMem;
+               dcMem.CreateCompatibleDC(dc);
+               dcMem.SelectBitmap(m_bmBall);
+
+               dc.BitBlt(m_ptCenter.x - m_sizeTotal.cx / 2,
+                               m_ptCenter.y - m_sizeTotal.cy / 2,
+                               m_sizeTotal.cx, m_sizeTotal.cy,
+                               dcMem, 0, 0, SRCCOPY);
+
+               m_ptCenter.x += m_sizeMove.cx;
+               m_ptCenter.y += m_sizeMove.cy;
+
+               if((m_ptCenter.x + m_sizeRadius.cx >= rcClient.right) ||
+                       (m_ptCenter.x - m_sizeRadius.cx <= 0))
+               {
+                       m_sizeMove.cx = -m_sizeMove.cx;
+               }
+
+               if((m_ptCenter.y + m_sizeRadius.cy >= rcClient.bottom) ||
+                       (m_ptCenter.y - m_sizeRadius.cy <= 0))
+               {
+                       m_sizeMove.cy = -m_sizeMove.cy;
+               }
+
+               return 0;
+       }
+
+       LRESULT OnColor(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               switch(wID)
+               {
+                case ID_BLACK:
+                       ClearAllColors();
+                       m_bBlack = !(m_bBlack);
+                       break;
+                case ID_WHITE:
+                       ClearAllColors();
+                       m_bWhite = !(m_bWhite);
+                       break;
+                case ID_RED:
+                       m_bRed = !(m_bRed);
+                       m_bBlack = FALSE;
+                       m_bWhite = FALSE;
+                       break;
+                case ID_GREEN:
+                       m_bGreen = !(m_bGreen);
+                       m_bBlack = FALSE;
+                       m_bWhite = FALSE;
+                       break;
+                case ID_BLUE:
+                       m_bBlue = !(m_bBlue);
+                       m_bBlack = FALSE;
+                       m_bWhite = FALSE;
+                       break;
+                default:
+                       TCHAR buff[256];
+                       ::LoadString(_Module.GetResourceInstance(), IDS_UNKCOLOR, buff, 255);
+                       MessageBox(buff);
+                       return 1;
+               }
+               MixColors();
+               return 0;
+       }
+
+       LRESULT OnCustomColor(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               CColorDialog dlgColor(m_clrBall);
+               if(dlgColor.DoModal() == IDOK)
+               {
+                       m_clrBall = dlgColor.GetColor();
+                       ClearAllColors();
+                       m_bCustom = TRUE;
+                       UpdateColorButtons();
+                       MakeNewBall();
+                       Invalidate();
+               }
+               return 0;
+       }
+
+       LRESULT OnChangeSpeed(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               m_bFastSpeed = (wID == ID_SPEED_FAST) ? TRUE : FALSE;
+               UpdateSpeedButtons();
+               KillTimer(1);
+#if (_ATL_VER >= 0x0300)
+               if(!SetTimer(1, m_bFastSpeed ? 0 : 100))
+#else
+               if(!SetTimer(1, m_bFastSpeed ? 0 : 100, NULL))
+#endif //(_ATL_VER == 0x0300)
+               {
+                       MessageBox(_T("Not enough timers available for this window."),
+                                       _T("MDI:Bounce"), MB_ICONEXCLAMATION | MB_OK);
+                       DestroyWindow();
+               }
+               return 0;
+       }
+};
+
+class CBounceWnd : public CMDIChildWindowImpl<CBounceWnd>
+{
+public:
+       CBounceView* m_pView;
+       CUpdateUIBase* m_pUpdateUI;
+
+       CBounceWnd(CUpdateUIBase* pUpdateUI) : m_pView(NULL), m_pUpdateUI(pUpdateUI)
+       { }
+
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_BOUNCETYPE)
+
+       HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
+                       DWORD dwStyle = 0, DWORD dwExStyle = 0,
+                       UINT nMenuID = 0, LPVOID lpCreateParam = NULL)
+       {
+               CFrameWndClassInfo& wci = GetWndClassInfo();
+               wci.m_lpszCursorID = IDC_UPARROW;
+               return CMDIChildWindowImpl<CBounceWnd>::Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, nMenuID, lpCreateParam);
+       }
+
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+
+       BEGIN_MSG_MAP(CBounceWnd)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               CHAIN_CLIENT_COMMANDS()
+               CHAIN_MSG_MAP(CMDIChildWindowImpl<CBounceWnd>)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL& bHandled)
+       {
+               m_pView = new CBounceView(m_pUpdateUI);
+               RECT rect = { 0, 0, 1, 1 };
+               m_hWndClient = m_pView->Create(m_hWnd, rect, NULL, WS_CHILD | WS_VISIBLE, WS_EX_CLIENTEDGE);
+
+               bHandled = FALSE;
+               return 1;
+       }
+};
+
+
+class CAboutDlg : public CDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTDLG };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               CenterWindow(GetParent());
+               return (LRESULT)TRUE;
+       }
+
+       LRESULT OnCloseCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+};
+
+
+class CMDIFrame : public CMDIFrameWindowImpl<CMDIFrame>, CUpdateUI<CMDIFrame>,
+               public CMessageFilter, public CUpdateUIObject
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
+
+       CMDICommandBarCtrl m_CmdBar;
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               return CMDIFrameWindowImpl<CMDIFrame>::PreTranslateMessage(pMsg);
+       }
+
+       virtual BOOL DoUpdate()
+       {
+               UIUpdateToolBar();
+               return FALSE;
+       }
+
+       BEGIN_MSG_MAP(CMDIFrame)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEWBOUNCE, OnBounce)
+               COMMAND_ID_HANDLER(ID_FILE_NEWHELLO, OnHello)
+               COMMAND_ID_HANDLER(ID_WINDOW_CASCADE, OnWindowCascade)
+               COMMAND_ID_HANDLER(ID_WINDOW_TILE_HORZ, OnWindowTile)
+               COMMAND_ID_HANDLER(ID_WINDOW_ARRANGE, OnWindowArrangeIcons)
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
+               CHAIN_MDI_CHILD_COMMANDS()
+               CHAIN_MSG_MAP(CUpdateUI<CMDIFrame>)
+               CHAIN_MSG_MAP(CMDIFrameWindowImpl<CMDIFrame>)
+       END_MSG_MAP()
+
+       BEGIN_UPDATE_UI_MAP(CMDIFrame)
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_BLACK,  UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_RED,    UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_GREEN,  UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_BLUE,   UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_WHITE,  UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_CUSTOM, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_SPEED_SLOW, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_SPEED_FAST, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+       END_UPDATE_UI_MAP()
+
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               // Create MDIClient
+               CreateMDIClient();
+
+               // Create MDI CommandBar
+               m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+               m_CmdBar.SetMDIClient(m_hWndClient);
+               m_CmdBar.AttachMenu(GetMenu());
+               SetMenu(NULL);
+
+               // Create Toolbar
+               HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+               UIAddToolBar(hWndToolBar);
+
+               // Create Rebar
+               CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+               AddSimpleReBarBand(m_CmdBar);
+               AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+
+               CreateSimpleStatusBar(_T("Ready"));
+
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+
+               UIEnable(ID_BLACK, FALSE);
+               UIEnable(ID_RED, FALSE);
+               UIEnable(ID_GREEN, FALSE);
+               UIEnable(ID_BLUE, FALSE);
+               UIEnable(ID_WHITE, FALSE);
+               UIEnable(ID_CUSTOM, FALSE);
+               UIEnable(ID_SPEED_SLOW, FALSE);
+               UIEnable(ID_SPEED_FAST, FALSE);
+
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               pLoop->AddMessageFilter(this);
+               pLoop->AddUpdateUI(this);
+
+               return 0;
+       }
+
+
+       LRESULT OnMDISetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               UISetCheck(ID_BLACK, 0);
+               UISetCheck(ID_RED, 0);
+               UISetCheck(ID_GREEN, 0);
+               UISetCheck(ID_BLUE, 0);
+               UISetCheck(ID_WHITE, 0);
+               UISetCheck(ID_CUSTOM, 0);
+               UISetCheck(ID_SPEED_SLOW, 0);
+               UISetCheck(ID_SPEED_FAST, 0);
+
+               UIEnable(ID_BLACK, FALSE);
+               UIEnable(ID_RED, FALSE);
+               UIEnable(ID_GREEN, FALSE);
+               UIEnable(ID_BLUE, FALSE);
+               UIEnable(ID_WHITE, FALSE);
+               UIEnable(ID_CUSTOM, FALSE);
+               UIEnable(ID_SPEED_SLOW, FALSE);
+               UIEnable(ID_SPEED_FAST, FALSE);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnFileExit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+
+       LRESULT OnBounce(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               CBounceWnd* pChild = new CBounceWnd((CUpdateUIBase*)this);
+               pChild->CreateEx(m_hWndClient, NULL, _T("Bounce"));
+
+               return 0;
+       }
+
+       LRESULT OnHello(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               CHelloWnd* pChild = new CHelloWnd((CUpdateUIBase*)this);
+               pChild->CreateEx(m_hWndClient, NULL, _T("Hello"));
+
+               return 0;
+       }
+
+       LRESULT OnWindowCascade(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               MDICascade(0);
+               return 0;
+       }
+
+       LRESULT OnWindowTile(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               MDITile(MDITILE_HORIZONTAL);
+               return 0;
+       }
+
+       LRESULT OnWindowArrangeIcons(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               MDIIconArrange();
+               return 0;
+       }
+
+       LRESULT OnViewToolBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               BOOL bNew = !::IsWindowVisible(m_hWndToolBar);
+               ::ShowWindow(m_hWndToolBar, bNew ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_TOOLBAR, bNew);
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnViewStatusBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               BOOL bNew = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bNew ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bNew);
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnAppAbout(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/MDIDocVw/res/HelloDoc.ico b/include/WTL/Samples/MDIDocVw/res/HelloDoc.ico
new file mode 100644 (file)
index 0000000..5355f4a
Binary files /dev/null and b/include/WTL/Samples/MDIDocVw/res/HelloDoc.ico differ
diff --git a/include/WTL/Samples/MDIDocVw/res/MDI.ICO b/include/WTL/Samples/MDIDocVw/res/MDI.ICO
new file mode 100644 (file)
index 0000000..7eef0bc
Binary files /dev/null and b/include/WTL/Samples/MDIDocVw/res/MDI.ICO differ
diff --git a/include/WTL/Samples/MDIDocVw/res/Toolbar.bmp b/include/WTL/Samples/MDIDocVw/res/Toolbar.bmp
new file mode 100644 (file)
index 0000000..d3f5fdb
Binary files /dev/null and b/include/WTL/Samples/MDIDocVw/res/Toolbar.bmp differ
diff --git a/include/WTL/Samples/MDIDocVw/res/idr_boun.ico b/include/WTL/Samples/MDIDocVw/res/idr_boun.ico
new file mode 100644 (file)
index 0000000..9aa0291
Binary files /dev/null and b/include/WTL/Samples/MDIDocVw/res/idr_boun.ico differ
diff --git a/include/WTL/Samples/MDIDocVw/resource.h b/include/WTL/Samples/MDIDocVw/resource.h
new file mode 100644 (file)
index 0000000..9d39500
--- /dev/null
@@ -0,0 +1,39 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by MDI.rc
+//
+#define IDR_MAINFRAME                   2
+#define ID_BLACK                        20
+#define ID_RED                          21
+#define ID_GREEN                        22
+#define ID_BLUE                         23
+#define ID_WHITE                        24
+#define ID_CUSTOM                       25
+#define IDD_ABOUTDLG                    104
+#define IDR_HELLOTYPE                   129
+#define IDR_BOUNCETYPE                  31234
+#define ID_FILE_NEWHELLO                32771
+#define ID_FILE_NEWBOUNCE               32772
+#define ID_SPEED_SLOW                   32778
+#define ID_SPEED_FAST                   32779
+#define IDS_NOHELLOTEMPLATE             32780
+#define IDS_NOBOUNCETEMPLATE            32781
+#define ID_MIX                          32783
+#define IDS_UNKCOLOR                    32784
+#define ID_WINDOW_ARRANGEICONS          40003
+#define ID_WINDOW_MINIMIZEALL           40004
+#define ID_WINDOW_CASCADE2              57652
+#define ID_WINDOW_TILE_HORZ2            57653
+#define ID_WINDOW_TILE_VERT2            57654
+#define ID_WINDOW_SPLIT2                57655
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        106
+#define _APS_NEXT_COMMAND_VALUE         40005
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/MDIDocVw/stdafx.cpp b/include/WTL/Samples/MDIDocVw/stdafx.cpp
new file mode 100644 (file)
index 0000000..f23d975
--- /dev/null
@@ -0,0 +1,5 @@
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
diff --git a/include/WTL/Samples/MDIDocVw/stdafx.h b/include/WTL/Samples/MDIDocVw/stdafx.h
new file mode 100644 (file)
index 0000000..38979a3
--- /dev/null
@@ -0,0 +1,6 @@
+#include <atlbase.h>
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#include <atlwin.h>
diff --git a/include/WTL/Samples/MTPad/MTPad.cpp b/include/WTL/Samples/MTPad/MTPad.cpp
new file mode 100644 (file)
index 0000000..ada56ea
--- /dev/null
@@ -0,0 +1,57 @@
+#include "stdatl.h"
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atlctrlx.h>
+#include <atldlgs.h>
+#include <atlmisc.h>
+#ifndef _WIN32_WCE
+#include <atlctrlw.h>
+#include <atlprint.h>
+#include <atlfind.h>
+#include "finddlg.h"
+#endif // _WIN32_WCE
+
+#include "resource.h"
+
+// Globals
+#define WM_UPDATEROWCOL                (WM_USER + 1000)
+
+LPCTSTR lpcstrMTPadRegKey = _T("Software\\Microsoft\\WTL Samples\\MTPad");
+
+LPCTSTR lpcstrFilter = 
+       _T("All Files (*.*)\0*.*\0")
+       _T("Text Files (*.txt)\0*.txt\0")
+       _T("C++ Files (*.cpp)\0*.cpp\0")
+       _T("Include Files (*.h)\0*.h\0")
+       _T("C Files (*.c)\0*.c\0")
+       _T("Inline Files (*.inl)\0*.inl\0")
+       _T("Ini Files (*.ini)\0*.ini\0")
+       _T("Batch Files (*.bat)\0*.bat\0")
+       _T("");
+
+#include "view.h"
+#include "aboutdlg.h"
+#include "mainfrm.h"
+
+#include "mtpad.h"
+
+CAppModule _Module;
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int nCmdShow)
+{
+       _Module.Init(NULL, hInstance);
+#ifndef _WIN32_WCE
+       HINSTANCE hInstRich = ::LoadLibrary(CRichEditCtrl::GetLibraryName());
+#endif // _WIN32_WCE
+
+       CThreadManager mgr;
+       int nRet = mgr.Run(lpCmdLine, nCmdShow);
+
+#ifndef _WIN32_WCE
+       ::FreeLibrary(hInstRich);
+#endif // _WIN32_WCE
+       _Module.Term();
+
+       return nRet;
+}
diff --git a/include/WTL/Samples/MTPad/MTPad.h b/include/WTL/Samples/MTPad/MTPad.h
new file mode 100644 (file)
index 0000000..6d8d7fd
--- /dev/null
@@ -0,0 +1,161 @@
+class CMTPadMsgLoop : public CMessageLoop
+{
+public:
+       CMainFrame m_wndFrame;
+
+       int Run(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               if(m_wndFrame.CreateEx() == NULL)
+               {
+                       ATLTRACE(_T("CMainFrame creation failed!\n"));
+                       return 0;
+               }
+
+               if(lpstrCmdLine[0] == 0)
+               {
+                       m_wndFrame.DoFileNew();
+               }
+               else    // file name specified at the command line
+               {
+                       // strip quotes (if any)
+                       LPTSTR lpstrCmd = lpstrCmdLine;
+                       if(lpstrCmd[0] == '"')
+                       {
+                               lpstrCmd++;
+                               for(int i = 0; i < lstrlen(lpstrCmd); i++)
+                               {
+                                       if(lpstrCmd[i] == '"')
+                                       {
+                                               lpstrCmd[i] = 0;
+                                               break;
+                                       }
+                               }
+                       }
+                       // get full path and file name
+                       TCHAR szPathName[MAX_PATH];
+                       LPTSTR lpstrFileName = NULL;
+#ifndef _WIN32_WCE
+                       ::GetFullPathName(lpstrCmd, MAX_PATH, szPathName, &lpstrFileName);
+#endif // _WIN32_WCE
+                       // open file
+                       if(m_wndFrame.DoFileOpen(szPathName, lpstrFileName))
+                       {
+#ifndef _WIN32_WCE
+                               m_wndFrame.m_mru.AddToList(szPathName);
+#endif // _WIN32_WCE
+                       }
+               }
+
+               m_wndFrame.ShowWindow(nCmdShow);
+
+               return CMessageLoop::Run();
+       }
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               return m_wndFrame.PreTranslateMessage(pMsg);
+       }
+
+       virtual BOOL OnIdle(int)
+       {
+               m_wndFrame.UpdateUIAll();
+               return FALSE;
+       }
+};
+
+class CThreadManager
+{
+public:
+       // thread init param
+       struct _RunData
+       {
+               LPTSTR lpstrCmdLine;
+               int nCmdShow;
+       };
+
+       // thread proc
+       static DWORD WINAPI RunThread(LPVOID lpData)
+       {
+               CMTPadMsgLoop theLoop;
+               _Module.AddMessageLoop(&theLoop);
+
+               _RunData* pData = (_RunData*)lpData;
+               int nRet = theLoop.Run(pData->lpstrCmdLine, pData->nCmdShow);
+               delete pData;
+
+               _Module.RemoveMessageLoop();
+               return nRet;
+       }
+
+       DWORD m_dwCount;
+       HANDLE m_arrThreadHandles[MAXIMUM_WAIT_OBJECTS - 1];
+
+       CThreadManager() : m_dwCount(0)
+       { }
+
+// Operations
+       DWORD AddThread(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               if(m_dwCount == (MAXIMUM_WAIT_OBJECTS - 1))
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create ANY MORE threads!!!"), _T("MTPad"), MB_OK);
+                       return 0;
+               }
+
+               _RunData* pData = new _RunData;
+               pData->lpstrCmdLine = lpstrCmdLine;
+               pData->nCmdShow = nCmdShow;
+               DWORD dwThreadID;
+               HANDLE hThread = ::CreateThread(NULL, 0, RunThread, pData, 0, &dwThreadID);
+               if(hThread == NULL)
+               {
+                       ::MessageBox(NULL, _T("Cannot create thread!!!"), _T("MTPad"), MB_OK);
+                       return 0;
+               }
+
+               m_arrThreadHandles[m_dwCount] = hThread;
+               m_dwCount++;
+               return dwThreadID;
+       }
+
+       void RemoveThread(DWORD dwIndex)
+       {
+               ::CloseHandle(m_arrThreadHandles[dwIndex]);
+               if(dwIndex != (m_dwCount - 1))
+                       m_arrThreadHandles[dwIndex] = m_arrThreadHandles[m_dwCount - 1];
+               m_dwCount--;
+       }
+
+       int Run(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               MSG msg;
+               // force message queue to be created
+               ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+
+               AddThread(lpstrCmdLine, nCmdShow);
+
+               int nRet = m_dwCount;
+               DWORD dwRet;
+               while(m_dwCount > 0)
+               {
+                       dwRet = ::MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles, FALSE, INFINITE, QS_ALLINPUT);
+
+                       if(dwRet == 0xFFFFFFFF)
+                               ::MessageBox(NULL, _T("Wait for multiple objects failed!!!"), _T("MTPad"), MB_OK);
+                       else if(dwRet >= WAIT_OBJECT_0 && dwRet <= (WAIT_OBJECT_0 + m_dwCount - 1))
+                               RemoveThread(dwRet - WAIT_OBJECT_0);
+                       else if(dwRet == (WAIT_OBJECT_0 + m_dwCount))
+                       {
+                               ::GetMessage(&msg, NULL, 0, 0);
+                               if(msg.message == WM_USER)
+                                       AddThread(_T(""), SW_SHOWNORMAL);
+                               else
+                                       ::MessageBeep((UINT)-1);
+                       }
+                       else
+                               ::MessageBeep((UINT)-1);
+               }
+
+               return nRet;
+       }
+};
diff --git a/include/WTL/Samples/MTPad/MTPad.sln b/include/WTL/Samples/MTPad/MTPad.sln
new file mode 100644 (file)
index 0000000..5ab7a84
--- /dev/null
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MTPad", "MTPad.vcproj", "{3A5F348A-39BD-425E-8DB3-E82300A9D0CF}"
+EndProject
+Global
+       GlobalSection(SolutionConfiguration) = preSolution
+               ConfigName.0 = Debug
+               ConfigName.1 = Release
+       EndGlobalSection
+       GlobalSection(ProjectDependencies) = postSolution
+       EndGlobalSection
+       GlobalSection(ProjectConfiguration) = postSolution
+               {3A5F348A-39BD-425E-8DB3-E82300A9D0CF}.Debug.ActiveCfg = Debug|Win32
+               {3A5F348A-39BD-425E-8DB3-E82300A9D0CF}.Debug.Build.0 = Debug|Win32
+               {3A5F348A-39BD-425E-8DB3-E82300A9D0CF}.Release.ActiveCfg = Release|Win32
+               {3A5F348A-39BD-425E-8DB3-E82300A9D0CF}.Release.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+       EndGlobalSection
+       GlobalSection(ExtensibilityAddIns) = postSolution
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/MTPad/aboutdlg.h b/include/WTL/Samples/MTPad/aboutdlg.h
new file mode 100644 (file)
index 0000000..96eabc5
--- /dev/null
@@ -0,0 +1,23 @@
+class CAboutDlg : public CDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTDLG };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+               return (LRESULT)TRUE;
+       }
+
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/MTPad/finddlg.h b/include/WTL/Samples/MTPad/finddlg.h
new file mode 100644 (file)
index 0000000..811babb
--- /dev/null
@@ -0,0 +1,71 @@
+
+#ifndef __FindReplaceDialogWithMessageFilter_h__
+#define __FindReplaceDialogWithMessageFilter_h__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error FindReplaceDialogWithMessageFilter.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error FindReplaceDialogWithMessageFilter.h requires atlwin.h to be included first
+#endif
+
+class CFindReplaceDialogWithMessageFilter :
+       public CFindReplaceDialogImpl<CFindReplaceDialogWithMessageFilter>,
+       public CMessageFilter
+{
+protected:
+       CMessageLoop* m_messageLoop;
+
+public:
+       CFindReplaceDialogWithMessageFilter(CMessageLoop* messageLoop) :
+               m_messageLoop(messageLoop)
+       {
+       }
+
+public:
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               HWND hWndFocus = ::GetFocus();
+               if((m_hWnd == hWndFocus) || this->IsChild(hWndFocus))
+                       return this->IsDialogMessage(pMsg);
+
+               return FALSE;
+       }
+
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+
+       BEGIN_MSG_MAP(CFindReplaceDialogWithMessageFilter)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_messageLoop)
+                       m_messageLoop->AddMessageFilter(this);
+
+               bHandled = FALSE;
+               return 0;
+       }
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               if(m_messageLoop)
+                       m_messageLoop->RemoveMessageFilter(this);
+
+               bHandled = FALSE;
+               return 0;
+       }
+};
+
+#endif //__FindReplaceDialogWithMessageFilter_h__
diff --git a/include/WTL/Samples/MTPad/mainfrm.h b/include/WTL/Samples/MTPad/mainfrm.h
new file mode 100644 (file)
index 0000000..6fc6687
--- /dev/null
@@ -0,0 +1,687 @@
+#define FILE_MENU_POSITION     0
+#define RECENT_MENU_POSITION   11
+
+class CMainFrame : 
+       public CFrameWindowImpl<CMainFrame>, 
+       public CUpdateUI<CMainFrame>
+#ifndef _WIN32_WCE
+       , public CPrintJobInfo
+#endif // _WIN32_WCE
+{
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME);
+
+#ifndef _WIN32_WCE
+       CCommandBarCtrl m_CmdBar;
+       CRecentDocumentList m_mru;
+#endif // _WIN32_WCE
+       CMultiPaneStatusBarCtrl m_sbar;
+       CEditView m_view;
+       BOOL m_bModified;
+
+#ifndef _WIN32_WCE
+       CPrinterT<true> printer;
+       CDevModeT<true> devmode;
+       CPrintPreviewWindow prev;
+       CEnhMetaFileT<true> enhmetafile;
+#endif // _WIN32_WCE
+       CRect m_rcMargin;
+       HWND m_hWndOldClient;
+       HWND m_hWndToolBarPP;
+       CSimpleValArray<long> m_arrPages;
+
+       CMainFrame() : m_bModified(FALSE), m_rcMargin(1000, 1000, 1000, 1000)
+       {
+#ifndef _WIN32_WCE
+               printer.OpenDefaultPrinter();
+               devmode.CopyFromPrinter(printer);
+#endif // _WIN32_WCE
+       }
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if(m_view.PreTranslateMessage(pMsg))
+                       return TRUE;
+
+               return CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg);
+       }
+
+       BEGIN_MSG_MAP(CMainFrame)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_CLOSE, OnClose)
+               MESSAGE_HANDLER(WM_UPDATEROWCOL, OnUpdateRowCol)
+#ifndef _WIN32_WCE
+               COMMAND_ID_HANDLER(ID_FILE_PRINT, OnFilePrint)
+               COMMAND_ID_HANDLER(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
+               COMMAND_ID_HANDLER(ID_FILE_PAGE_SETUP, OnFilePageSetup)
+               COMMAND_ID_HANDLER(ID_PP_CLOSE, OnPrintPreviewClose)
+               COMMAND_ID_HANDLER(ID_PP_BACK, OnPrintPreviewBack)
+               COMMAND_ID_HANDLER(ID_PP_FORWARD, OnPrintPreviewForward)
+#endif // _WIN32_WCE
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+               COMMAND_ID_HANDLER(ID_FILE_OPEN, OnFileOpen)
+               COMMAND_ID_HANDLER(ID_FILE_SAVE, OnFileSave)
+               COMMAND_ID_HANDLER(ID_FILE_SAVE_AS, OnFileSaveAs)
+#ifndef _WIN32_WCE
+               COMMAND_RANGE_HANDLER(ID_FILE_MRU_FIRST, ID_FILE_MRU_LAST, OnFileRecent)
+#endif // _WIN32_WCE
+               COMMAND_ID_HANDLER(ID_FILE_NEW_WINDOW, OnFileNewWindow)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
+               CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
+               CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
+               CHAIN_COMMANDS_MEMBER((m_view))
+       END_MSG_MAP()
+
+       BEGIN_UPDATE_UI_MAP(CMainFrame)
+               UPDATE_ELEMENT(ID_EDIT_UNDO,       UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_CUT,        UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_COPY,       UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_PASTE,      UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_CLEAR,      UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_SELECT_ALL, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_FIND,       UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_REPEAT,     UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_REPLACE,    UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_EDIT_WORD_WRAP,  UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR,    UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_PP_BACK,        UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(ID_PP_FORWARD, UPDUI_TOOLBAR)
+       END_UPDATE_UI_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+#ifndef _WIN32_WCE
+               // create command bar window
+               HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+               // atach menu
+               m_CmdBar.AttachMenu(GetMenu());
+               // load command bar images
+               m_CmdBar.LoadImages(IDR_MAINFRAME);
+               // remove old menu
+               SetMenu(NULL);
+
+               HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+               CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+               AddSimpleReBarBand(hWndCmdBar);
+               AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+#else
+               CreateSimpleCECommandBar(MAKEINTRESOURCE(IDR_MAINFRAME));
+               CreateSimpleToolBar();
+#endif // _WIN32_WCE
+
+               CreateSimpleStatusBar();
+               m_sbar.SubclassWindow(m_hWndStatusBar);
+               int arrParts[] =
+               {
+                       ID_DEFAULT_PANE,
+                       ID_ROW_PANE,
+                       ID_COL_PANE
+               };
+               m_sbar.SetPanes(arrParts, sizeof(arrParts) / sizeof(int), false);
+
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, 
+                       WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | 
+                       ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL 
+#ifndef _WIN32_WCE
+                       | ES_SAVESEL | ES_SELECTIONBAR,
+                       WS_EX_CLIENTEDGE);
+#else // _WIN32_WCE
+                       );
+#endif // _WIN32_WCE
+
+#ifndef _WIN32_WCE
+               UIAddToolBar(hWndToolBar);
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+#endif // _WIN32_WCE
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+
+               SendMessage(WM_UPDATEROWCOL);   // update row and col indicators
+
+#ifndef _WIN32_WCE
+               m_hWndToolBarPP = CreateSimpleToolBarCtrl(m_hWnd, IDR_PRINTPREVIEWBAR, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE, ATL_IDW_TOOLBAR + 1);
+               AddSimpleReBarBand(m_hWndToolBarPP, NULL, TRUE);
+               ::SendMessage(m_hWndToolBar, RB_SHOWBAND, 2, FALSE);    // print preview toolbar is band #2
+
+               UIAddToolBar(m_hWndToolBarPP);
+#endif // _WIN32_WCE
+
+#ifndef _WIN32_WCE
+               HMENU hMenu = m_CmdBar.GetMenu();
+               HMENU hFileMenu = ::GetSubMenu(hMenu, FILE_MENU_POSITION);
+#ifdef _DEBUG
+               // absolute position, can change if menu changes
+               TCHAR szMenuString[100];
+               ::GetMenuString(hFileMenu, RECENT_MENU_POSITION, szMenuString, sizeof(szMenuString), MF_BYPOSITION);
+               ATLASSERT(lstrcmp(szMenuString, _T("Recent &Files")) == 0);
+#endif //_DEBUG
+               HMENU hMruMenu = ::GetSubMenu(hFileMenu, RECENT_MENU_POSITION);
+               m_mru.SetMenuHandle(hMruMenu);
+
+               m_mru.ReadFromRegistry(lpcstrMTPadRegKey);
+#endif // _WIN32_WCE
+
+               return 0;
+       }
+
+       LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               bHandled = !m_view.QueryClose();
+               return 0;
+       }
+
+       LRESULT OnUpdateRowCol(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               TCHAR szBuff[100];
+               wsprintf(szBuff, _T("Row: %i"), m_view.m_nRow + 1);
+               m_sbar.SetPaneText(ID_ROW_PANE, szBuff);
+               wsprintf(szBuff, _T("Col: %i"), m_view.m_nCol + 1);
+               m_sbar.SetPaneText(ID_COL_PANE, szBuff);
+               return 0;
+       }
+
+       LRESULT UpdateTitle()
+       {
+               int nAppendLen = lstrlen(m_view.m_strFileName);
+
+               TCHAR strTitleBase[256];
+               ::LoadString(_Module.GetResourceInstance(), IDR_MAINFRAME, strTitleBase, 255);
+               int nBaseLen = lstrlen(strTitleBase);
+
+               // 1 == "*" (optional), 3 == " - ", 1 == null termination
+               LPTSTR lpstrFullTitle = (LPTSTR)_alloca((nAppendLen + nBaseLen + 1 + 3 + 1) * sizeof(TCHAR));
+
+               lstrcpy(lpstrFullTitle, m_view.m_strFileName);
+               if(m_bModified)
+                       lstrcat(lpstrFullTitle, _T("*"));
+               lstrcat(lpstrFullTitle, _T(" - "));
+               lstrcat(lpstrFullTitle, strTitleBase);
+
+               SetWindowText(lpstrFullTitle);
+
+               return 0;
+       }
+
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               DoFileNew();
+               return 0;
+       }
+
+       void DoFileNew()
+       {
+               if(m_view.QueryClose())
+               {
+                       m_view.SetWindowText(NULL);
+                       m_view.Init(_T(""), _T("Untitled"));
+                       UpdateTitle();
+               }
+       }
+
+       LRESULT OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CFileDialog dlg(TRUE, NULL, _T(""), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, lpcstrFilter);
+               int nRet = dlg.DoModal();
+
+               if(nRet == IDOK)
+               {
+                       ATLTRACE(_T("File path: %s\n"), dlg.m_ofn.lpstrFile);
+                       BOOL bRet = m_view.QueryClose();
+                       if(!bRet)
+                       {
+                               if(!DoFileSaveAs())
+                                       return 0;
+                       }
+
+                       if(DoFileOpen(dlg.m_ofn.lpstrFile, dlg.m_ofn.lpstrFileTitle))
+                       {
+#ifndef _WIN32_WCE
+                               m_mru.AddToList(dlg.m_ofn.lpstrFile);
+                               m_mru.WriteToRegistry(lpcstrMTPadRegKey);
+#endif // _WIN32_WCE
+                       }
+               }
+
+               return 0;
+       }
+
+       BOOL DoFileOpen(LPCTSTR lpstrFileName, LPCTSTR lpstrFileTitle)
+       {
+               BOOL bRet = m_view.LoadFile(lpstrFileName);
+               if(bRet)
+               {
+                       m_view.Init(lpstrFileName, lpstrFileTitle);
+                       UpdateTitle();
+               }
+               else
+                       MessageBox(_T("Error reading file!\n"));
+
+               return bRet;
+       }
+
+       LRESULT OnFileSave(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               if(m_view.m_strFilePath[0] != 0)
+               {
+                       if(m_view.SaveFile(m_view.m_strFilePath))
+                       {
+                               m_view.SetModify(FALSE);
+#ifndef _WIN32_WCE
+                               m_mru.AddToList(m_view.m_strFilePath);
+                               m_mru.WriteToRegistry(lpcstrMTPadRegKey);
+#endif // _WIN32_WCE
+                       }
+                       else
+                       {
+                               MessageBox(_T("Error writing file!\n"));
+                       }
+               }
+               else
+               {
+                       if(m_view.DoFileSaveAs())
+                       {
+                               UpdateTitle();
+#ifndef _WIN32_WCE
+                               m_mru.AddToList(m_view.m_strFilePath);
+                               m_mru.WriteToRegistry(lpcstrMTPadRegKey);
+#endif // _WIN32_WCE
+                       }
+               }
+
+               return 0;
+       }
+
+       LRESULT OnFileSaveAs(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               if(m_view.DoFileSaveAs())
+               {
+                       UpdateTitle();
+#ifndef _WIN32_WCE
+                       m_mru.AddToList(m_view.m_strFilePath);
+                       m_mru.WriteToRegistry(lpcstrMTPadRegKey);
+#endif // _WIN32_WCE
+               }
+               return 0;
+       }
+
+       BOOL DoFileSaveAs()
+       {
+               BOOL bRet = FALSE;
+               CFileDialog dlg(FALSE);
+               int nRet = dlg.DoModal();
+
+               if(nRet == IDOK)
+               {
+                       ATLTRACE(_T("File path: %s\n"), dlg.m_ofn.lpstrFile);
+                       bRet = m_view.SaveFile(dlg.m_ofn.lpstrFile);
+                       if(bRet)
+                       {
+                               m_view.Init(dlg.m_ofn.lpstrFile, dlg.m_ofn.lpstrFileTitle);
+                               UpdateTitle();
+                       }
+                       else
+                               MessageBox(_T("Error writing file!\n"));
+               }
+
+               return bRet;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnFileRecent(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // check if we have to save the current one
+               if(!m_view.QueryClose())
+               {
+                       if(!m_view.DoFileSaveAs())
+                               return 0;
+               }
+               // get file name from the MRU list
+               TCHAR szFile[MAX_PATH];
+               if(m_mru.GetFromList(wID, szFile, MAX_PATH))
+               {
+                       // find file name without the path
+                       LPTSTR lpstrFileName = szFile;
+                       for(int i = lstrlen(szFile) - 1; i >= 0; i--)
+                       {
+                               if(szFile[i] == '\\')
+                               {
+                                       lpstrFileName = &szFile[i + 1];
+                                       break;
+                               }
+                       }
+                       // open file
+                       if(DoFileOpen(szFile, lpstrFileName))
+                               m_mru.MoveToTop(wID);
+                       else
+                               m_mru.RemoveFromList(wID);
+                       m_mru.WriteToRegistry(lpcstrMTPadRegKey);
+               }
+               else
+               {
+                       ::MessageBeep(MB_ICONERROR);
+               }
+
+               return 0;
+       }
+#endif // _WIN32_WCE
+
+       LRESULT OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
+               return 0;
+       }
+
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               static BOOL bNew = TRUE;        // initially visible
+               bNew = !bNew;
+               ::SendMessage(m_hWndToolBar, RB_SHOWBAND, 1, bNew); // toolbar is band #1
+               UISetCheck(ID_VIEW_TOOLBAR, bNew);
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bNew = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bNew ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bNew);
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+       LRESULT OnContextMenu(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if((HWND)wParam == m_view.m_hWnd)
+               {
+                       CMenu menuContext;
+                       menuContext.LoadMenu(IDR_CONTEXTMENU);
+                       CMenuHandle menuPopup(menuContext.GetSubMenu(0));
+#ifndef _WIN32_WCE
+                       m_CmdBar.TrackPopupMenu(menuPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, LOWORD(lParam), HIWORD(lParam));
+#else
+                       TrackPopupMenuEx(menuPopup, TPM_LEFTALIGN, LOWORD(lParam), HIWORD(lParam), m_hWndCECommandBar, NULL);
+#endif // _WIN32_WCE
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+
+               return 0;
+       }
+
+       void UpdateUIAll()
+       {
+               BOOL bModified = m_view.GetModify();
+               if(bModified != m_bModified)
+               {
+                       m_bModified = bModified;
+                       UpdateTitle();
+               }
+
+               UIEnable(ID_EDIT_UNDO, m_view.CanUndo());
+#ifndef _WIN32_WCE
+               UIEnable(ID_EDIT_PASTE, m_view.CanPaste(CF_TEXT));
+
+               BOOL bSel = (m_view.GetSelectionType() != SEL_EMPTY);
+
+               UIEnable(ID_EDIT_CUT, bSel);
+               UIEnable(ID_EDIT_COPY, bSel);
+               UIEnable(ID_EDIT_CLEAR, bSel);
+#endif // _WIN32_WCE
+
+               BOOL bNotEmpty = (m_view.GetWindowTextLength() > 0);
+               UIEnable(ID_EDIT_SELECT_ALL, bNotEmpty);
+               UIEnable(ID_EDIT_FIND, bNotEmpty);
+               UIEnable(ID_EDIT_REPEAT, bNotEmpty);
+               UIEnable(ID_EDIT_REPLACE, bNotEmpty);
+
+               UISetCheck(ID_EDIT_WORD_WRAP, m_view.m_bWordWrap);
+
+#ifndef _WIN32_WCE
+               if(prev.IsWindow() && (prev.GetStyle() & WS_VISIBLE) != 0)
+               {
+                       UIEnable(ID_PP_BACK, (prev.m_nCurPage > prev.m_nMinPage));
+                       UIEnable(ID_PP_FORWARD, prev.m_nCurPage < prev.m_nMaxPage);
+               }
+#endif // _WIN32_WCE
+
+               UIUpdateToolBar();
+       }
+
+#ifndef _WIN32_WCE
+//print job info callback
+       virtual bool IsValidPage(UINT /*nPage*/)
+       {
+               return true;
+       }
+
+       virtual bool PrintPage(UINT nPage, HDC hDC)
+       {
+               if (nPage >= (UINT)m_arrPages.GetSize())
+                       return false;
+
+               RECT rcPage;
+               rcPage.left = rcPage.top = 0;
+               rcPage.bottom = GetDeviceCaps(hDC, PHYSICALHEIGHT);
+               rcPage.right = GetDeviceCaps(hDC, PHYSICALWIDTH);
+
+               rcPage.right = MulDiv(rcPage.right, 1440, GetDeviceCaps(hDC, LOGPIXELSX));
+               rcPage.bottom = MulDiv(rcPage.bottom, 1440, GetDeviceCaps(hDC, LOGPIXELSY));
+
+               RECT rcOutput = rcPage;
+               //convert from 1/1000" to twips
+               rcOutput.left += MulDiv(m_rcMargin.left, 1440, 1000);
+               rcOutput.right -= MulDiv(m_rcMargin.right, 1440, 1000);
+               rcOutput.top += MulDiv(m_rcMargin.top, 1440, 1000);
+               rcOutput.bottom -= MulDiv(m_rcMargin.bottom, 1440, 1000);
+
+               
+               FORMATRANGE fr;
+               fr.hdc = hDC;
+               fr.hdcTarget = hDC;
+               fr.rc = rcOutput;
+               fr.rcPage = rcPage;
+               fr.chrg.cpMin = 0;
+               fr.chrg.cpMax = -1;
+               fr.chrg.cpMin = m_arrPages[nPage];
+
+               // We have to adjust the origin because 0,0 is not at the corner of the paper
+               // but is at the corner of the printable region
+               int nOffsetX = GetDeviceCaps(hDC, PHYSICALOFFSETX);
+               int nOffsetY = GetDeviceCaps(hDC, PHYSICALOFFSETY);
+               SetViewportOrgEx(hDC, -nOffsetX, -nOffsetY, NULL);
+               m_view.FormatRange(fr, TRUE);
+               m_view.DisplayBand(&rcOutput);
+
+               //Cleanup cache in richedit
+               m_view.FormatRange(NULL, FALSE);
+               return true;
+       }
+
+       bool LayoutPages()
+       {
+               CDC dc = printer.CreatePrinterDC(devmode);
+               if(dc.IsNull())
+                       return false;
+
+               RECT rcPage;
+               rcPage.left = rcPage.top = 0;
+               rcPage.bottom = GetDeviceCaps(dc, PHYSICALHEIGHT);
+               rcPage.right = GetDeviceCaps(dc, PHYSICALWIDTH);
+               // We have to adjust the origin because 0,0 is not at the corner of the paper
+               // but is at the corner of the printable region
+               int nOffsetX = dc.GetDeviceCaps(PHYSICALOFFSETX);
+               int nOffsetY = dc.GetDeviceCaps(PHYSICALOFFSETY);
+               dc.SetViewportOrg(-nOffsetX, -nOffsetY);
+               rcPage.right = MulDiv(rcPage.right, 1440, GetDeviceCaps(dc, LOGPIXELSX));
+               rcPage.bottom = MulDiv(rcPage.bottom, 1440, GetDeviceCaps(dc, LOGPIXELSY));
+
+               RECT rcOutput = rcPage;
+               //convert from 1/1000" to twips
+               rcOutput.left += MulDiv(m_rcMargin.left, 1440, 1000);
+               rcOutput.right -= MulDiv(m_rcMargin.right, 1440, 1000);
+               rcOutput.top += MulDiv(m_rcMargin.top, 1440, 1000);
+               rcOutput.bottom -= MulDiv(m_rcMargin.bottom, 1440, 1000);
+               
+               FORMATRANGE fr;
+               fr.hdc = dc;
+               fr.hdcTarget = dc;
+               fr.rc = rcOutput;
+               fr.rcPage = rcPage;
+               fr.chrg.cpMin = 0;
+               fr.chrg.cpMax = -1;
+
+               LONG n = (LONG)m_view.GetTextLength();
+               m_arrPages.RemoveAll();
+               while (1)
+               {
+                       m_arrPages.Add(fr.chrg.cpMin);
+                       LONG lRet = m_view.FormatRange(fr, FALSE);
+                       if((lRet - fr.chrg.cpMin) == -1)
+                       {
+                               m_arrPages.RemoveAt(m_arrPages.GetSize()-1);
+                               break;
+                       }
+                       else
+                               fr.chrg.cpMin = lRet;
+                       if (fr.chrg.cpMin >= n)
+                               break;
+               }
+
+               m_view.FormatRange(NULL, FALSE);
+
+               return true;
+       }
+
+       LRESULT OnFilePrint(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               if(!LayoutPages())
+               {
+                       MessageBox(_T("Print operation failed"), _T("MTPad"), MB_ICONERROR | MB_OK);
+                       return 0;
+               }
+
+               CPrintDialog dlg(FALSE);
+               dlg.m_pd.hDevMode = devmode.CopyToHDEVMODE();
+               dlg.m_pd.hDevNames = printer.CopyToHDEVNAMES();
+               dlg.m_pd.nMinPage = 1;
+               dlg.m_pd.nMaxPage = (WORD)m_arrPages.GetSize();
+               dlg.m_pd.nFromPage = 1;
+               dlg.m_pd.nToPage = (WORD)m_arrPages.GetSize();
+               dlg.m_pd.Flags &= ~PD_NOPAGENUMS;
+
+               if (dlg.DoModal() == IDOK)
+               {
+                       devmode.CopyFromHDEVMODE(dlg.m_pd.hDevMode);
+                       printer.ClosePrinter();
+                       printer.OpenPrinter(dlg.m_pd.hDevNames, devmode.m_pDevMode);
+
+                       CPrintJob job;
+                       int nMin=0;
+                       int nMax = m_arrPages.GetSize() - 1;
+                       if(dlg.PrintRange() != FALSE)
+                       {
+                               nMin = dlg.m_pd.nFromPage - 1;
+                               nMax = dlg.m_pd.nToPage - 1;
+                       }
+
+                       job.StartPrintJob(false, printer, devmode.m_pDevMode, this, _T("MTPad Document"), nMin, nMax, (dlg.PrintToFile() != FALSE));
+               }
+
+               GlobalFree(dlg.m_pd.hDevMode);
+               GlobalFree(dlg.m_pd.hDevNames);
+
+               return 0;
+       }
+
+       LRESULT OnFilePrintPreview(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               bool bRet = LayoutPages();
+               if(!bRet)
+               {
+                       MessageBox(_T("Print preview operation failed"), _T("MTPad"), MB_ICONERROR | MB_OK);
+                       return 0;
+               }
+
+               prev.SetPrintPreviewInfo(printer, devmode.m_pDevMode, this, 0, m_arrPages.GetSize() - 1);
+               prev.SetPage(0);
+               RECT rcPos;
+               GetClientRect(&rcPos);
+               prev.Create(m_hWnd, rcPos);
+               prev.ShowWindow(SW_SHOW);
+               prev.SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
+
+               ::ShowWindow(m_hWndClient, SW_HIDE);
+               m_hWndOldClient = m_hWndClient;
+               m_hWndClient = prev;
+               ::SendMessage(m_hWndToolBar, RB_SHOWBAND, 1, FALSE);    // toolbar is band #1
+               ::SendMessage(m_hWndToolBar, RB_SHOWBAND, 2, TRUE); // print preview toolbar is band #2
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnFilePageSetup(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CPageSetupDialog dlg;
+               dlg.m_psd.hDevMode = devmode.CopyToHDEVMODE();
+               dlg.m_psd.hDevNames = printer.CopyToHDEVNAMES();
+               dlg.m_psd.rtMargin = m_rcMargin;
+
+               if (dlg.DoModal() == IDOK)
+               {
+                       devmode.CopyFromHDEVMODE(dlg.m_psd.hDevMode);
+                       printer.ClosePrinter();
+                       printer.OpenPrinter(dlg.m_psd.hDevNames, devmode.m_pDevMode);
+                       m_rcMargin = dlg.m_psd.rtMargin;
+               }
+
+               GlobalFree(dlg.m_psd.hDevMode);
+               GlobalFree(dlg.m_psd.hDevNames);
+
+               return 0;
+       }
+
+       LRESULT OnPrintPreviewClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               prev.DestroyWindow();
+               m_hWndClient = m_hWndOldClient;
+               ::ShowWindow(m_hWndClient, SW_SHOW);
+               ::SendMessage(m_hWndToolBar, RB_SHOWBAND, 1, TRUE); // toolbar is band #1
+               ::SendMessage(m_hWndToolBar, RB_SHOWBAND, 2, FALSE);    // print preview toolbar is band #2
+               UpdateLayout();
+               return 0;
+       }
+
+       LRESULT OnPrintPreviewForward(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               prev.NextPage();
+               return 0;
+       }
+       
+       LRESULT OnPrintPreviewBack(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               prev.PrevPage();
+               return 0;
+       }
+#endif // _WIN32_WCE
+};
diff --git a/include/WTL/Samples/MTPad/res/MTPad.ico b/include/WTL/Samples/MTPad/res/MTPad.ico
new file mode 100644 (file)
index 0000000..946eefc
Binary files /dev/null and b/include/WTL/Samples/MTPad/res/MTPad.ico differ
diff --git a/include/WTL/Samples/MTPad/res/MTPadDoc.ico b/include/WTL/Samples/MTPad/res/MTPadDoc.ico
new file mode 100644 (file)
index 0000000..d523c8a
Binary files /dev/null and b/include/WTL/Samples/MTPad/res/MTPadDoc.ico differ
diff --git a/include/WTL/Samples/MTPad/res/Toolbar.bmp b/include/WTL/Samples/MTPad/res/Toolbar.bmp
new file mode 100644 (file)
index 0000000..e67b85d
Binary files /dev/null and b/include/WTL/Samples/MTPad/res/Toolbar.bmp differ
diff --git a/include/WTL/Samples/MTPad/res/ToolbarCE.bmp b/include/WTL/Samples/MTPad/res/ToolbarCE.bmp
new file mode 100644 (file)
index 0000000..4f74918
Binary files /dev/null and b/include/WTL/Samples/MTPad/res/ToolbarCE.bmp differ
diff --git a/include/WTL/Samples/MTPad/res/printpre.bmp b/include/WTL/Samples/MTPad/res/printpre.bmp
new file mode 100644 (file)
index 0000000..2617f7f
Binary files /dev/null and b/include/WTL/Samples/MTPad/res/printpre.bmp differ
diff --git a/include/WTL/Samples/MTPad/resource.h b/include/WTL/Samples/MTPad/resource.h
new file mode 100644 (file)
index 0000000..858bf9c
--- /dev/null
@@ -0,0 +1,27 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by MTPad.rc
+//
+#define IDD_ABOUTDLG                    104
+#define IDR_PRINTPREVIEWBAR             108
+#define IDR_MAINFRAME                   128
+#define IDR_TEXTTYPE                    129
+#define IDR_CONTEXTMENU                 130
+#define ID_FILE_NEW_WINDOW              32771
+#define ID_EDIT_WORD_WRAP               40003
+#define ID_PP_BACK                      40006
+#define ID_PP_CLOSE                     40008
+#define ID_PP_FORWARD                   40011
+#define ID_ROW_PANE                     61403
+#define ID_COL_PANE                     61404
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        110
+#define _APS_NEXT_COMMAND_VALUE         40013
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/MTPad/resourcece.h b/include/WTL/Samples/MTPad/resourcece.h
new file mode 100644 (file)
index 0000000..b274440
--- /dev/null
@@ -0,0 +1,27 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+// Used by MTPadCE.rc
+//
+#define IDD_ABOUTDLG                    104
+#define IDR_PRINTPREVIEWBAR             108
+#define IDR_MAINFRAME                   128
+#define IDR_TEXTTYPE                    129
+#define IDR_CONTEXTMENU                 130
+#define ID_FILE_NEW_WINDOW              32771
+#define ID_EDIT_WORD_WRAP               40003
+#define ID_PP_BACK                      40006
+#define ID_PP_CLOSE                     40008
+#define ID_PP_FORWARD                   40011
+#define ID_ROW_PANE                     61403
+#define ID_COL_PANE                     61404
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        110
+#define _APS_NEXT_COMMAND_VALUE         40013
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/MTPad/stdatl.cpp b/include/WTL/Samples/MTPad/stdatl.cpp
new file mode 100644 (file)
index 0000000..22e2ff4
--- /dev/null
@@ -0,0 +1,5 @@
+#include "stdatl.h"
+
+#if (_ATL_VER < 0x0700) && !defined(_WIN32_WCE)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
diff --git a/include/WTL/Samples/MTPad/stdatl.h b/include/WTL/Samples/MTPad/stdatl.h
new file mode 100644 (file)
index 0000000..75132f8
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _WIN32_WCE
+
+#define WINVER         0x0500
+#define _WIN32_WINNT   0x0500
+#define _WIN32_IE      0x0501
+#define _RICHEDIT_VER  0x0200
+
+#else // _WIN32_WCE
+
+#define WINVER         0x0400
+#define _WIN32_IE      0x0400
+
+#endif // _WIN32_WCE
+
+#define _WTL_USE_CSTRING
+
+#include <atlbase.h>
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#include <atlwin.h>
diff --git a/include/WTL/Samples/MTPad/view.h b/include/WTL/Samples/MTPad/view.h
new file mode 100644 (file)
index 0000000..1c6d605
--- /dev/null
@@ -0,0 +1,349 @@
+class CEditView : 
+#ifndef _WIN32_WCE
+       public CWindowImpl<CEditView, CRichEditCtrl>,
+       public CRichEditCommands<CEditView>,
+       public CRichEditFindReplaceImpl<CEditView, CFindReplaceDialogWithMessageFilter>
+#else // _WIN32_WCE
+       public CWindowImpl<CEditView, CEdit>,
+       public CEditCommands<CEditView>
+#endif // _WIN32_WCE
+{
+protected:
+       typedef CEditView thisClass;
+#ifndef _WIN32_WCE
+       typedef CRichEditCommands<CEditView> editCommandsClass;
+       typedef CRichEditFindReplaceImpl<CEditView, CFindReplaceDialogWithMessageFilter> findReplaceClass;
+#else
+       typedef CEditCommands<CEditView> editCommandsClass;
+#endif
+
+public:
+#ifndef _WIN32_WCE
+       DECLARE_WND_SUPERCLASS(NULL, CRichEditCtrl::GetWndClassName())
+#else // _WIN32_WCE
+       DECLARE_WND_SUPERCLASS(NULL, CEdit::GetWndClassName())
+#endif // _WIN32_WCE
+
+       enum
+       {
+               cchTAB = 8,
+               nMaxBufferLen = 4000000
+       };
+
+       CFont m_font;
+       int m_nRow, m_nCol;
+       TCHAR m_strFilePath[MAX_PATH];
+       TCHAR m_strFileName[MAX_PATH];
+       BOOL m_bWordWrap;
+
+       CEditView() : 
+               m_nRow(0), m_nCol(0), 
+               m_bWordWrap(FALSE)
+       {
+               m_font = AtlGetDefaultGuiFont();
+               m_strFilePath[0] = 0;
+               m_strFileName[0] = 0;
+       }
+
+       void Sorry()
+       {
+               MessageBox(_T("Sorry, not yet implemented"), _T("MTPad"), MB_OK);
+       }
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+#ifndef _WIN32_WCE
+               // In non Multi-thread SDI cases, CFindReplaceDialogWithMessageFilter will add itself to the
+               // global message filters list.  In our case, we'll call it directly.
+               if(m_pFindReplaceDialog != NULL)
+               {
+                       if(m_pFindReplaceDialog->PreTranslateMessage(pMsg))
+                               return TRUE;
+               }
+#endif
+               return FALSE;
+       }
+
+       BEGIN_MSG_MAP(CEditView)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_KEYDOWN, OnKey)
+               MESSAGE_HANDLER(WM_KEYUP, OnKey)
+               MESSAGE_HANDLER(WM_LBUTTONDOWN, OnKey)
+
+               COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnEditPaste)
+               CHAIN_MSG_MAP_ALT(editCommandsClass, 1)
+
+#ifndef _WIN32_WCE
+               CHAIN_MSG_MAP_ALT(findReplaceClass, 1)
+               COMMAND_ID_HANDLER(ID_EDIT_WORD_WRAP, OnEditWordWrap)
+               COMMAND_ID_HANDLER(ID_FORMAT_FONT, OnViewFormatFont)
+#endif // _WIN32_WCE
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+               LimitText(nMaxBufferLen);
+               SetFont(m_font);
+
+               CClientDC dc(m_hWnd);
+               HFONT hOldFont = dc.SelectFont(m_font);
+               TEXTMETRIC tm;
+               dc.GetTextMetrics(&tm);
+               int nLogPix = dc.GetDeviceCaps(LOGPIXELSX);
+               dc.SelectFont(hOldFont);
+#ifndef _WIN32_WCE
+               int cxTab = ::MulDiv(tm.tmAveCharWidth * cchTAB, 1440, nLogPix);        // 1440 twips = 1 inch
+               if(cxTab != -1)
+               {
+                       PARAFORMAT pf;
+                       pf.cbSize = sizeof(PARAFORMAT);
+                       pf.dwMask = PFM_TABSTOPS;
+                       pf.cTabCount = MAX_TAB_STOPS;
+                       for(int i = 0; i < MAX_TAB_STOPS; i++)
+                               pf.rgxTabs[i] = (i + 1) * cxTab;
+                       SetParaFormat(pf);
+               }
+#endif // _WIN32_WCE
+               dc.SelectFont(hOldFont);
+
+               SetModify(FALSE);
+
+               return lRet;
+       }
+
+       LRESULT OnKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+               // calc caret position
+#ifndef _WIN32_WCE
+               long nStartPos, nEndPos;
+#else // _WIN32_WCE
+               int nStartPos, nEndPos;
+#endif // _WIN32_WCE
+               GetSel(nStartPos, nEndPos);
+               m_nRow = LineFromChar(nEndPos);
+               m_nCol = 0;
+               int nChar = nEndPos - LineIndex();
+               if(nChar > 0)
+               {
+                       LPTSTR lpstrLine = (LPTSTR)_alloca(max(2, (nChar + 1) * sizeof(TCHAR)));        // min = WORD for length
+                       nChar = GetLine(m_nRow, lpstrLine, nChar);
+                       for(int i = 0; i < nChar; i++)
+                       {
+                               if(lpstrLine[i] == _T('\t'))
+                                       m_nCol = ((m_nCol / cchTAB) + 1) * cchTAB;
+                               else
+                                       m_nCol++;
+                       }
+               }
+
+               ::SendMessage(GetParent(), WM_UPDATEROWCOL, 0, 0L);
+
+               return lRet;
+       }
+
+       LRESULT OnEditPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+#ifndef _WIN32_WCE
+               PasteSpecial(CF_TEXT);
+#else // _WIN32_WCE
+               Paste();
+#endif // _WIN32_WCE
+               return 0;
+       }
+
+#ifndef _WIN32_WCE
+       LRESULT OnEditWordWrap(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               m_bWordWrap = !m_bWordWrap;
+               int nLine = m_bWordWrap ? 0 : 1;
+               SetTargetDevice(NULL, nLine);
+
+               return 0;
+       }
+
+       LRESULT OnViewFormatFont(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CFontDialog dlg;
+               m_font.GetLogFont(&dlg.m_lf);
+               dlg.m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
+               if (dlg.DoModal() == IDOK)
+               {
+                       m_font.DeleteObject();
+                       m_font.CreateFontIndirect(&dlg.m_lf);
+                       SetFont(m_font);
+               }
+               return 0;
+       }
+#endif // _WIN32_WCE
+
+// Overrides from CEditFindReplaceImpl
+#ifndef _WIN32_WCE
+       CFindReplaceDialogWithMessageFilter* CreateFindReplaceDialog(BOOL bFindOnly, // TRUE for Find, FALSE for FindReplace
+                       LPCTSTR lpszFindWhat,
+                       LPCTSTR lpszReplaceWith = NULL,
+                       DWORD dwFlags = FR_DOWN,
+                       HWND hWndParent = NULL)
+       {
+               // In non Multi-Threaded SDI cases, we'd pass in the message loop to CFindReplaceDialogWithMessageFilter.
+               // In our case, we'll call PreTranslateMessage directly from this class.
+               //CFindReplaceDialogWithMessageFilter* findReplaceDialog =
+               //      new CFindReplaceDialogWithMessageFilter(_Module.GetMessageLoop());
+               CFindReplaceDialogWithMessageFilter* findReplaceDialog =
+                       new CFindReplaceDialogWithMessageFilter(NULL);
+
+               if(findReplaceDialog == NULL)
+               {
+                       ::MessageBeep(MB_ICONHAND);
+               }
+               else
+               {
+                       HWND hWndFindReplace = findReplaceDialog->Create(bFindOnly,
+                               lpszFindWhat, lpszReplaceWith, dwFlags, hWndParent);
+                       if(hWndFindReplace == NULL)
+                       {
+                               delete findReplaceDialog;
+                               findReplaceDialog = NULL;
+                       }
+                       else
+                       {
+                               findReplaceDialog->SetActiveWindow();
+                               findReplaceDialog->ShowWindow(SW_SHOW);
+                       }
+               }
+
+               return findReplaceDialog;
+       }
+
+       DWORD GetFindReplaceDialogFlags(void) const
+       {
+               DWORD dwFlags = FR_HIDEWHOLEWORD;
+
+               if(m_bFindDown)
+                       dwFlags |= FR_DOWN;
+               if(m_bMatchCase)
+                       dwFlags |= FR_MATCHCASE;
+
+               return dwFlags;
+       }
+#endif // _WIN32_WCE
+
+       BOOL LoadFile(LPCTSTR lpstrFilePath)
+       {
+               _ASSERTE(lpstrFilePath != NULL);
+
+               HANDLE hFile = ::CreateFile(lpstrFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+               if(hFile == INVALID_HANDLE_VALUE)
+                       return FALSE;
+
+#ifndef _WIN32_WCE
+               EDITSTREAM es;
+               es.dwCookie = (DWORD)hFile;
+               es.dwError = 0;
+               es.pfnCallback = StreamReadCallback;
+               StreamIn(SF_TEXT, es);
+
+               ::CloseHandle(hFile);
+
+               return !(BOOL)es.dwError;
+#else // _WIN32_WCE
+               //TODO - figure out what to do here instead...
+               ::CloseHandle(hFile);
+
+               return FALSE;
+#endif // _WIN32_WCE
+       }
+
+       static DWORD CALLBACK StreamReadCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb)
+       {
+               _ASSERTE(dwCookie != 0);
+               _ASSERTE(pcb != NULL);
+
+               return !::ReadFile((HANDLE)dwCookie, pbBuff, cb, (LPDWORD)pcb, NULL);
+       }
+
+       BOOL SaveFile(LPTSTR lpstrFilePath)
+       {
+               _ASSERTE(lpstrFilePath != NULL);
+
+               HANDLE hFile = ::CreateFile(lpstrFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+               if(hFile == INVALID_HANDLE_VALUE)
+                       return FALSE;
+
+#ifndef _WIN32_WCE
+               EDITSTREAM es;
+               es.dwCookie = (DWORD)hFile;
+               es.dwError = 0;
+               es.pfnCallback = StreamWriteCallback;
+               StreamOut(SF_TEXT, es);
+
+               ::CloseHandle(hFile);
+
+               return !(BOOL)es.dwError;
+#else // _WIN32_WCE
+               //TODO - figure out what to do here instead...
+               ::CloseHandle(hFile);
+
+               return FALSE;
+#endif // _WIN32_WCE
+       }
+
+       static DWORD CALLBACK StreamWriteCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb)
+       {
+               _ASSERTE(dwCookie != 0);
+               _ASSERTE(pcb != NULL);
+
+               return !::WriteFile((HANDLE)dwCookie, pbBuff, cb, (LPDWORD)pcb, NULL);
+       }
+
+       void Init(LPCTSTR lpstrFilePath, LPCTSTR lpstrFileName)
+       {
+               lstrcpy(m_strFilePath, lpstrFilePath);
+               lstrcpy(m_strFileName, lpstrFileName);
+               SetModify(FALSE);
+       }
+
+       BOOL QueryClose()
+       {
+               if(!GetModify())
+                       return TRUE;
+
+               CWindow wndMain(GetParent());
+               TCHAR szBuff[MAX_PATH + 30];
+               wsprintf(szBuff, _T("Save changes to %s ?"), m_strFileName);
+               int nRet = wndMain.MessageBox(szBuff, _T("MTPad"), MB_YESNOCANCEL | MB_ICONEXCLAMATION);
+
+               if(nRet == IDCANCEL)
+                       return FALSE;
+               else if(nRet == IDYES)
+               {
+                       if(!DoFileSaveAs())
+                               return FALSE;
+               }
+
+               return TRUE;
+       }
+
+       BOOL DoFileSaveAs()
+       {
+               BOOL bRet = FALSE;
+
+               CFileDialog dlg(FALSE, NULL, m_strFilePath, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, lpcstrFilter);
+               int nRet = dlg.DoModal();
+
+               if(nRet == IDOK)
+               {
+                       ATLTRACE(_T("File path: %s\n"), dlg.m_ofn.lpstrFile);
+                       bRet = SaveFile(dlg.m_ofn.lpstrFile);
+                       if(bRet)
+                               Init(dlg.m_ofn.lpstrFile, dlg.m_ofn.lpstrFileTitle);
+                       else
+                               MessageBox(_T("Error writing file!\n"));
+               }
+
+               return bRet;
+       }
+};
diff --git a/include/WTL/Samples/MiniPie/MiniPie.cpp b/include/WTL/Samples/MiniPie/MiniPie.cpp
new file mode 100644 (file)
index 0000000..58e0e42
--- /dev/null
@@ -0,0 +1,45 @@
+// MiniPie.cpp : main source file for MiniPie.exe
+//
+
+#include "stdafx.h"
+
+#ifdef WIN32_PLATFORM_PSPC
+#include "resourceppc.h"
+#else
+#include "resourcesp.h"
+#endif
+
+#include "MiniPieFrame.h"
+
+CAppModule _Module;
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+       HRESULT hRes = CMiniPieFrame::ActivatePreviousInstance(hInstance, lpstrCmdLine);
+
+       if(FAILED(hRes) || S_FALSE == hRes)
+       {
+               return hRes;
+       }
+
+       hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       AtlInitCommonControls(ICC_DATE_CLASSES);
+       SHInitExtraControls();
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       AtlAxWinInit();
+
+       int nRet = CMiniPieFrame::AppRun(lpstrCmdLine, nCmdShow);
+
+       AtlAxWinTerm();
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
+
diff --git a/include/WTL/Samples/MiniPie/MiniPie.sln b/include/WTL/Samples/MiniPie/MiniPie.sln
new file mode 100644 (file)
index 0000000..de25883
--- /dev/null
@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MiniPie", "MiniPie.vcproj", "{092E7424-7886-4FB7-AD3F-66F479C1A0DF}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               Debug|Windows Mobile 6 Professional SDK (ARMV4I) = Debug|Windows Mobile 6 Professional SDK (ARMV4I)
+               Debug|Windows Mobile 6 Standard SDK (ARMV4I) = Debug|Windows Mobile 6 Standard SDK (ARMV4I)
+               Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               Release|Windows Mobile 6 Professional SDK (ARMV4I) = Release|Windows Mobile 6 Professional SDK (ARMV4I)
+               Release|Windows Mobile 6 Standard SDK (ARMV4I) = Release|Windows Mobile 6 Standard SDK (ARMV4I)
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 6 Professional SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 6 Standard SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 6 Standard SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 6 Standard SDK (ARMV4I).Build.0 = Debug|Windows Mobile 6 Standard SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Debug|Windows Mobile 6 Standard SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 6 Standard SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 6 Professional SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 6 Standard SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 6 Standard SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 6 Standard SDK (ARMV4I).Build.0 = Release|Windows Mobile 6 Standard SDK (ARMV4I)
+               {092E7424-7886-4FB7-AD3F-66F479C1A0DF}.Release|Windows Mobile 6 Standard SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 6 Standard SDK (ARMV4I)
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/MiniPie/MiniPie.suo b/include/WTL/Samples/MiniPie/MiniPie.suo
new file mode 100644 (file)
index 0000000..b100dbb
Binary files /dev/null and b/include/WTL/Samples/MiniPie/MiniPie.suo differ
diff --git a/include/WTL/Samples/MiniPie/MiniPie.vcxproj b/include/WTL/Samples/MiniPie/MiniPie.vcxproj
new file mode 100644 (file)
index 0000000..56ddd53
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Template|Win32">
+      <Configuration>Template</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+
+  <PropertyGroup Label="Globals">
+  </PropertyGroup>
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Template|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+  </PropertyGroup>
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup />
+
+  <ItemDefinitionGroup></ItemDefinitionGroup>
+  <ItemGroup></ItemGroup>
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
diff --git a/include/WTL/Samples/MiniPie/MiniPie.vcxproj.user b/include/WTL/Samples/MiniPie/MiniPie.vcxproj.user
new file mode 100644 (file)
index 0000000..ace9a86
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff --git a/include/WTL/Samples/MiniPie/MiniPieFrame.cpp b/include/WTL/Samples/MiniPie/MiniPieFrame.cpp
new file mode 100644 (file)
index 0000000..d4d22fe
--- /dev/null
@@ -0,0 +1,269 @@
+// MiniPieFrame.cpp : implementation of the CMiniPieFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#ifdef WIN32_PLATFORM_PSPC
+#include "resourceppc.h"
+#else
+#include "resourcesp.h"
+#endif
+
+#include "UrlDlg.h"
+#include "MiniPieFrame.h"
+
+BOOL CMiniPieFrame::PreTranslateMessage(MSG* pMsg)
+{
+       if(CFrameWindowImpl<CMiniPieFrame>::PreTranslateMessage(pMsg))
+               return TRUE; 
+
+       if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+          (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+               return FALSE;
+
+       if (m_bFullScreen && pMsg->message == WM_KEYUP && 
+               (pMsg->wParam == VK_F1 ||  pMsg->wParam == VK_F2))
+               SetFullScreen(false);
+
+       HWND hWndCtl = ::GetFocus();
+       if(IsChild(hWndCtl))
+       {
+               // find a direct child of the dialog from the window that has focus
+               while(::GetParent(hWndCtl) != m_hWnd)
+                       hWndCtl = ::GetParent(hWndCtl);
+
+               // give control a chance to translate this message
+               if(::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0)
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+bool CMiniPieFrame::AppNewInstance(LPCTSTR lpstrCmdLine)
+{
+       Navigate(lpstrCmdLine);
+       return true;
+}
+
+void CMiniPieFrame::AppSave()
+{
+       CAppInfo info;
+       info.Save( m_bFullScreen, L"Full");
+       bool bStatus = (UIGetState(ID_VIEW_STATUS_BAR) & UPDUI_CHECKED) == UPDUI_CHECKED;
+       info.Save(bStatus, L"Status");
+#ifdef WIN32_PLATFORM_PSPC
+    VARIANT_BOOL vb;
+       m_spIWebBrowser2->get_AddressBar(&vb);
+       info.Save(vb, L"Address");
+#endif
+}
+
+void CMiniPieFrame::UpdateLayout(BOOL bResizeBars)
+{
+       RECT rect = { 0 };
+       GetClientRect(&rect);
+
+       // resize status bar
+       if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
+       {
+               if(bResizeBars)
+                       ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0);
+               RECT rectSB = { 0 };
+               ::GetWindowRect(m_hWndStatusBar, &rectSB);
+               rect.top += rectSB.bottom - rectSB.top;
+       }
+       // resize client window
+       if(m_hWndClient != NULL)
+               ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
+                       rect.right - rect.left, rect.bottom - rect.top,
+                       SWP_NOZORDER | SWP_NOACTIVATE);
+}
+
+BOOL CMiniPieFrame::OnIdle()
+{
+       UIUpdateToolBar();
+       UIUpdateStatusBar();
+       return FALSE;
+}
+
+BOOL CMiniPieFrame::SetCommandButton(INT iID, bool bRight)
+{
+       TBBUTTONINFO tbbi = { sizeof(TBBUTTONINFO), TBIF_TEXT | TBIF_COMMAND | TBIF_BYINDEX };
+       tbbi.idCommand =  iID;
+       tbbi.pszText = (LPTSTR)AtlLoadString(iID);
+       return CMenuBarCtrl(m_hWndCECommandBar).SetButtonInfo(bRight, &tbbi);
+}
+
+void CMiniPieFrame::Navigate(LPCTSTR sUrl)
+{
+       CComBSTR bsUrl = sUrl;
+    m_spIWebBrowser2->Navigate(bsUrl, NULL, NULL, NULL, NULL);
+}
+
+LRESULT CMiniPieFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CAppInfo info;
+
+       // Full screen mode delayed restoration 
+       bool bFull = false;
+       info.Restore(bFull, L"Full");
+       if (bFull)
+               PostMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
+
+       CreateSimpleCEMenuBar();
+#ifdef WIN32_PLATFORM_WFSP // SmartPhone
+       AtlActivateBackKey(m_hWndCECommandBar);
+#endif 
+       UIAddToolBar(m_hWndCECommandBar);
+       SetCommandButton(ID_APP_EXIT);
+
+       // StatusBar state restoration 
+       bool bVisible = true;
+       info.Restore(bVisible, L"Status");
+       DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_TOP;
+       if (bVisible)
+               dwStyle |= WS_VISIBLE;
+
+       // StatusBar creation 
+       CreateSimpleStatusBar(ATL_IDS_IDLEMESSAGE, dwStyle);
+       UIAddStatusBar(m_hWndStatusBar);
+       UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+
+       // Browser view creation
+       m_hWndClient = m_browser.Create(m_hWnd, NULL, _T("Microsoft.PIEDocView"),
+                     WS_CHILD | WS_VISIBLE | WS_BORDER, 0, ID_BROWSER);
+
+    ATLVERIFY(SUCCEEDED(m_browser.QueryControl(&m_spIWebBrowser2)));
+    ATLVERIFY(SUCCEEDED(AtlAdviseSinkMap(this, true)));
+
+       // Navigation menu initialization
+       UIEnable(IDM_BACK, FALSE);
+       UIEnable(IDM_FORWARD, FALSE);
+       UIEnable(IDM_STOP, FALSE);
+       UIEnable(IDM_REFRESH, FALSE);
+
+#ifdef WIN32_PLATFORM_PSPC 
+       // PPC Address bar state restoration
+    VARIANT_BOOL vb = ATL_VARIANT_TRUE;
+       info.Restore(vb, L"Address");
+       m_spIWebBrowser2->put_AddressBar(vb);
+       UISetCheck(ID_VIEW_ADDRESSBAR, vb == ATL_VARIANT_TRUE);
+#endif 
+
+       // register object for message filtering and idle updates
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       ATLASSERT(pLoop != NULL);
+       pLoop->AddMessageFilter(this);
+       pLoop->AddIdleHandler(this);
+
+       return 0;
+}
+
+LRESULT CMiniPieFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+    ATLVERIFY(SUCCEEDED(AtlAdviseSinkMap(this, false)));
+       PostMessage(WM_CLOSE);
+       return 0;
+}
+
+LRESULT CMiniPieFrame::OnFullScreen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       SetFullScreen(!m_bFullScreen );
+       return TRUE;
+}
+
+LRESULT CMiniPieFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+       ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+       UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+       UpdateLayout();
+       return 0;
+}
+
+#ifdef WIN32_PLATFORM_PSPC
+LRESULT CMiniPieFrame::OnViewAddressBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+    VARIANT_BOOL vb;
+       m_spIWebBrowser2->get_AddressBar(&vb);
+       m_spIWebBrowser2->put_AddressBar(vb == ATL_VARIANT_TRUE ? ATL_VARIANT_FALSE : ATL_VARIANT_TRUE);
+       UISetCheck(ID_VIEW_ADDRESSBAR, vb == ATL_VARIANT_FALSE);
+       return 0;
+}
+
+// Specialization: create a PPC about dialog menubar 
+LRESULT CStdSimpleDialog<IDD_ABOUTBOX>::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CreateMenuBar(ATL_IDM_MENU_DONE);
+       StdPlatformInit();
+       StdShidInit();
+       return TRUE;
+}
+#endif
+
+LRESULT CMiniPieFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CStdSimpleDialog<IDD_ABOUTBOX> dlg;
+       FSDoModal(dlg);
+       return 0;
+}
+
+LRESULT CMiniPieFrame::OnOpenURL(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+    CUrlDlg dlg;
+    if (FSDoModal(dlg) == IDOK)
+               Navigate(dlg.GetUrl());
+       return 0;
+}
+
+LRESULT CMiniPieFrame::OnBrowserCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       HRESULT (IWebBrowser::*cmd[])(void)  = 
+       {
+               &IWebBrowser::GoForward, // wID == IDM_FORWARD
+               &IWebBrowser::GoBack, 
+               &IWebBrowser::GoHome, 
+               &IWebBrowser::Refresh, 
+               &IWebBrowser::Stop
+       };
+
+       (m_spIWebBrowser2->*cmd[wID - IDM_FORWARD])();
+       return 0;
+}
+
+// IWebBrowser2 event handlers
+
+void __stdcall CMiniPieFrame::OnBeforeNavigate2(IDispatch* /*pDisp*/, VARIANT * /*pvtURL*/, 
+                                              VARIANT * /*pvtFlags*/, VARIANT * /*pvtTargetFrameName*/,
+                                              VARIANT * /*pvtPostData*/, VARIANT * /*pvtHeaders*/, 
+                                              VARIANT_BOOL * /*pvbCancel*/)
+{
+    UISetText(ID_TITLE, L"Loading ...");
+       SetCommandButton(IDM_STOP);
+    UIEnable(IDM_STOP, TRUE);
+    UIEnable(IDM_REFRESH, FALSE);
+}
+
+void __stdcall CMiniPieFrame::OnBrowserTitleChange(BSTR bstrTitleText)
+{
+       CString sTitle;
+       sTitle.Format(L"\t%s\t", bstrTitleText);
+    UISetText(ID_TITLE, sTitle); 
+}
+
+void __stdcall CMiniPieFrame::OnNavigateComplete2(IDispatch* /*pDisp*/, VARIANT * /*pvtURL*/)
+{
+    UIEnable(IDM_REFRESH, TRUE);
+}
+
+void __stdcall CMiniPieFrame::OnDocumentComplete(IDispatch* /*pDisp*/, VARIANT * /*pvtURL*/)
+{
+       SetCommandButton(IDM_REFRESH);
+    UIEnable(IDM_STOP, FALSE);
+}
+
+void __stdcall CMiniPieFrame::OnCommandStateChange(long lCommand, BOOL bEnable)
+{
+       UIEnable(IDM_FORWARD - CSC_NAVIGATEFORWARD + lCommand, bEnable);
+}
diff --git a/include/WTL/Samples/MiniPie/MiniPieFrame.h b/include/WTL/Samples/MiniPie/MiniPieFrame.h
new file mode 100644 (file)
index 0000000..22467a5
--- /dev/null
@@ -0,0 +1,98 @@
+// MiniPieFrame.h : interface of the CMiniPieFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#define ID_TITLE 0             // Document title uses StatusBar pane 0  
+#define ID_BROWSER 1   // DispEvent ID
+
+class CMiniPieFrame : 
+       public CFrameWindowImpl<CMiniPieFrame>, 
+       public CUpdateUI<CMiniPieFrame>,
+       public CAppWindow<CMiniPieFrame>,
+       public CFullScreenFrame<CMiniPieFrame>,
+       public CMessageFilter, public CIdleHandler,
+    public IDispEventImpl<ID_BROWSER, CMiniPieFrame>
+{
+public:
+       DECLARE_APP_FRAME_CLASS(NULL, IDR_MAINFRAME, L"Software\\WTL\\MiniPie")
+
+// Data members
+    CAxWindow m_browser;
+    CComPtr<IWebBrowser2> m_spIWebBrowser2;
+
+// Message filter
+       virtual BOOL PreTranslateMessage(MSG* pMsg);
+
+// CAppWindow operations
+       bool AppNewInstance( LPCTSTR lpstrCmdLine);
+       void AppSave();
+
+// Implementation
+       void UpdateLayout(BOOL bResizeBars = TRUE);
+       BOOL SetCommandButton(INT iID, bool bRight = false);
+       void Navigate(LPCTSTR sUrl);
+
+// Idle handler and UI map
+       virtual BOOL OnIdle();
+
+       BEGIN_UPDATE_UI_MAP(CMiniPieFrame)
+               UPDATE_ELEMENT(ID_TITLE, UPDUI_STATUSBAR)
+               UPDATE_ELEMENT(ID_VIEW_FULLSCREEN, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_ADDRESSBAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(IDM_BACK, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(IDM_FORWARD, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(IDM_STOP, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+               UPDATE_ELEMENT(IDM_REFRESH, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
+       END_UPDATE_UI_MAP()
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CMiniPieFrame)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_VIEW_FULLSCREEN, OnFullScreen)
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+#ifdef WIN32_PLATFORM_PSPC
+               COMMAND_ID_HANDLER(ID_VIEW_ADDRESSBAR, OnViewAddressBar)
+#endif
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_RANGE_HANDLER(IDM_FORWARD, IDM_STOP, OnBrowserCmd)
+               COMMAND_ID_HANDLER(IDM_OPENURL, OnOpenURL)
+               CHAIN_MSG_MAP(CAppWindow<CMiniPieFrame>)
+               CHAIN_MSG_MAP(CFullScreenFrame<CMiniPieFrame>)
+               CHAIN_MSG_MAP(CUpdateUI<CMiniPieFrame>)
+               CHAIN_MSG_MAP(CFrameWindowImpl<CMiniPieFrame>)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnFullScreen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+#ifdef WIN32_PLATFORM_PSPC
+       LRESULT OnViewAddressBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+#endif
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnBrowserCmd(WORD /*wNotifyCode*/, WORD wID/**/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnOpenURL(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+
+// IWebBrowser2 event map and handlers
+       BEGIN_SINK_MAP(CMiniPieFrame)
+        SINK_ENTRY(ID_BROWSER, DISPID_BEFORENAVIGATE2, OnBeforeNavigate2)
+        SINK_ENTRY(ID_BROWSER, DISPID_TITLECHANGE, OnBrowserTitleChange)
+        SINK_ENTRY(ID_BROWSER, DISPID_NAVIGATECOMPLETE2, OnNavigateComplete2)
+        SINK_ENTRY(ID_BROWSER, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
+        SINK_ENTRY(ID_BROWSER, DISPID_COMMANDSTATECHANGE, OnCommandStateChange)
+    END_SINK_MAP()
+
+private:
+    void __stdcall OnBeforeNavigate2(IDispatch* pDisp, VARIANT * pvtURL, 
+                                     VARIANT * /*pvtFlags*/, VARIANT * pvtTargetFrameName,
+                                     VARIANT * /*pvtPostData*/, VARIANT * /*pvtHeaders*/, 
+                                     VARIANT_BOOL * /*pvbCancel*/);
+    void __stdcall OnBrowserTitleChange(BSTR bstrTitleText);
+    void __stdcall OnNavigateComplete2(IDispatch* pDisp, VARIANT * pvtURL);
+    void __stdcall OnDocumentComplete(IDispatch* pDisp, VARIANT * pvtURL);
+    void __stdcall OnCommandStateChange(long lCommand, BOOL bEnable);
+};
diff --git a/include/WTL/Samples/MiniPie/UrlDlg.cpp b/include/WTL/Samples/MiniPie/UrlDlg.cpp
new file mode 100644 (file)
index 0000000..728cdd8
--- /dev/null
@@ -0,0 +1,53 @@
+// UrlDlg.cpp : implementation of the CUrlDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#ifdef WIN32_PLATFORM_PSPC
+#include "resourceppc.h"
+#else
+#include "resourcesp.h"
+#endif
+
+#include "UrlDlg.h"
+
+LRESULT CUrlDlg::CEditUrl::OnKey(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+{
+       if (wParam == VK_RETURN)
+       {
+               if (uMsg == WM_KEYDOWN)
+                       GetParent().SendMessage(WM_COMMAND, IDOK);
+       }
+       else
+               bHandled = FALSE;
+       return 1;
+}
+
+const LPCTSTR CUrlDlg::m_sTypes[3] = {L"http://", L"file://", L"res://"};
+
+LPCTSTR CUrlDlg::GetUrl(void)
+{
+       return CString(m_sTypes[m_iType]) + m_strUrl;
+}
+
+void CUrlDlg::StdCloseDialog(WORD wID)
+{
+       if (wID == IDOK)
+       {
+               m_iType = m_lbType.GetCurSel();
+               DoDataExchange(TRUE);
+       }
+       EndDialog(wID);
+}
+
+LRESULT CUrlDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+       CreateMenuBar(IDM_EDIT);
+       DoDataExchange();
+       for (int i = 0; i < 3; i++)
+               m_lbType.AddString(m_sTypes[i]);
+       m_lbType.SetCurSel(m_iType = 0);
+       m_Ed.SetFocus();
+    return bHandled = FALSE;  
+}
+
diff --git a/include/WTL/Samples/MiniPie/UrlDlg.h b/include/WTL/Samples/MiniPie/UrlDlg.h
new file mode 100644 (file)
index 0000000..90e55fb
--- /dev/null
@@ -0,0 +1,64 @@
+// UrlDlg.h : interface of the CUrlDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CUrlDlg : 
+       public CStdDialogResizeImpl<CUrlDlg>,   
+       public CWinDataExchange<CUrlDlg>
+{
+public:
+       class CEditUrl : // a CEdit handling VK_RETURN and Edit commands
+               public CWindowImpl<CEditUrl, CEdit>, public CEditCommands<CEditUrl>
+       {
+       public:
+               DECLARE_WND_SUPERCLASS(L"MiniPie.EditUrl", CEdit::GetWndClassName())
+
+               BEGIN_MSG_MAP(CEditUrl)
+                       MESSAGE_RANGE_HANDLER(WM_KEYFIRST, WM_KEYLAST, OnKey)
+               ALT_MSG_MAP(1)
+                       CHAIN_MSG_MAP_ALT(CEditCommands<CEditUrl>, 1)
+               END_MSG_MAP()
+
+               LRESULT OnKey(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled);
+       };
+
+       enum { IDD = IDD_URL };
+       static const LPCTSTR m_sTypes[3];
+
+#ifdef WIN32_PLATFORM_PSPC
+       CListBox m_lbType;
+#else
+       CSpinListBox m_lbType;
+#endif
+       CEditUrl m_Ed;
+       int m_iType;
+       CString m_strUrl;
+
+       LPCTSTR GetUrl(void);
+       void StdCloseDialog(WORD wID);
+
+       BEGIN_DLGRESIZE_MAP(CUrlDlg)
+               DLGRESIZE_CONTROL(IDC_EDIT_URL, DLSZ_SIZE_X | DLSZ_SIZE_Y)      
+       END_DLGRESIZE_MAP()
+
+       BEGIN_DDX_MAP(CUrlDlg)
+               DDX_CONTROL_HANDLE(IDC_TYPE_LIST, m_lbType)
+               DDX_CONTROL(IDC_EDIT_URL, m_Ed)
+               DDX_TEXT(IDC_EDIT_URL, m_strUrl)
+       END_DDX_MAP()
+
+    BEGIN_MSG_MAP(CUrlDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+#ifdef WIN32_PLATFORM_PSPC
+               MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
+#endif
+               CHAIN_COMMANDS_ALT_MEMBER(m_Ed, 1)
+               CHAIN_MSG_MAP(CStdDialogResizeImpl<CUrlDlg>)
+    END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+};
+
+
diff --git a/include/WTL/Samples/MiniPie/res/MiniPie.ico b/include/WTL/Samples/MiniPie/res/MiniPie.ico
new file mode 100644 (file)
index 0000000..3bf85d3
Binary files /dev/null and b/include/WTL/Samples/MiniPie/res/MiniPie.ico differ
diff --git a/include/WTL/Samples/MiniPie/resourceppc.h b/include/WTL/Samples/MiniPie/resourceppc.h
new file mode 100644 (file)
index 0000000..d223323
--- /dev/null
@@ -0,0 +1,28 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MiniPieppc.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDD_URL                         101
+#define IDR_MAINFRAME                   128
+#define IDM_EDIT                        200
+#define IDC_TYPE_LIST                   1000
+#define IDC_EDIT_URL                    1001
+#define ID_VIEW_ADDRESSBAR              32773
+#define IDM_FORWARD                     32774
+#define IDM_BACK                        32775
+#define IDM_HOME                        32776
+#define IDM_REFRESH                     32777
+#define IDM_STOP                        32778
+#define IDM_OPENURL                     32779
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32780
+#define _APS_NEXT_CONTROL_VALUE         1002
+#define _APS_NEXT_SYMED_VALUE           102
+#endif
+#endif
diff --git a/include/WTL/Samples/MiniPie/resourcesp.h b/include/WTL/Samples/MiniPie/resourcesp.h
new file mode 100644 (file)
index 0000000..614bbef
--- /dev/null
@@ -0,0 +1,28 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MiniPiesp.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDD_URL                         101
+#define IDR_MAINFRAME                   128
+#define IDM_EDIT                        200
+#define IDC_TYPE_LIST                   1000
+#define IDC_EDIT_URL                    1001
+#define ID_VIEW_ADDRESSBAR              32773
+#define IDM_FORWARD                     32774
+#define IDM_BACK                        32775
+#define IDM_HOME                        32776
+#define IDM_REFRESH                     32777
+#define IDM_STOP                        32778
+#define IDM_OPENURL                     32779
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32780
+#define _APS_NEXT_CONTROL_VALUE         1002
+#define _APS_NEXT_SYMED_VALUE           102
+#endif
+#endif
diff --git a/include/WTL/Samples/MiniPie/stdafx.cpp b/include/WTL/Samples/MiniPie/stdafx.cpp
new file mode 100644 (file)
index 0000000..a51e0b5
--- /dev/null
@@ -0,0 +1,5 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     MiniPie.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/include/WTL/Samples/MiniPie/stdafx.h b/include/WTL/Samples/MiniPie/stdafx.h
new file mode 100644 (file)
index 0000000..9908022
--- /dev/null
@@ -0,0 +1,35 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#pragma once
+
+// Change this value to use different versions
+#define WINVER 0x0420
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS  // some CString constructors will be explicit
+#define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA
+#include <atlbase.h>
+#include <atlstr.h>
+
+#define _WTL_NO_CSTRING
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#include <atlhost.h>
+#include <atlctl.h>
+
+#include <pvdispid.h>
+#include <piedocvw.h>
+
+#include <tpcshell.h>
+#include <aygshell.h>
+#pragma comment(lib, "aygshell.lib")
+
+#include <atlframe.h>
+#include <atlmisc.h>
+#include <atlctrls.h>
+#include <atlddx.h>
+#define _WTL_CE_NO_ZOOMSCROLL
+#include <atlwince.h>
diff --git a/include/WTL/Samples/SPControls/SPcontrols.cpp b/include/WTL/Samples/SPControls/SPcontrols.cpp
new file mode 100644 (file)
index 0000000..66abdb5
--- /dev/null
@@ -0,0 +1,46 @@
+// SPcontrols.cpp : main source file for SPcontrols.exe
+//
+
+#include "stdafx.h"
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+
+#include <atlmisc.h>
+
+#define _WTL_CE_NO_ZOOMSCROLL
+#include <atlwince.h>
+
+#include "resource.h"
+#include "maindlg.h"
+
+CAppModule _Module;
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+
+       HRESULT hRes = CMainDlg::ActivatePreviousInstance(hInstance, lpstrCmdLine);
+       
+       if(FAILED(hRes) || S_FALSE == hRes)
+       {
+               return hRes;
+       }
+
+       hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       AtlInitCommonControls(ICC_UPDOWN_CLASS);
+       SHInitExtraControls();
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       int nRet = CMainDlg::AppRun(lpstrCmdLine, nCmdShow);
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
+
diff --git a/include/WTL/Samples/SPControls/SPcontrols.sln b/include/WTL/Samples/SPControls/SPcontrols.sln
new file mode 100644 (file)
index 0000000..a6fba5a
--- /dev/null
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPcontrols", "SPcontrols.vcproj", "{D6214D58-C765-4A2D-827C-41AE5D5F1DE8}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+               Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+               Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+               Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+               Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+               {D6214D58-C765-4A2D-827C-41AE5D5F1DE8}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/SPControls/maindlg.h b/include/WTL/Samples/SPControls/maindlg.h
new file mode 100644 (file)
index 0000000..a3f7bee
--- /dev/null
@@ -0,0 +1,166 @@
+// maindlg.h : interface of the CMainDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(_MAINDLG_H_)
+#define _MAINDLG_H_
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+
+class CMainDlg : public CAppStdDialogImpl<CMainDlg>,
+               public CMessageFilter, public CIdleHandler 
+{
+public:
+
+       DECLARE_APP_DLG_CLASS(NULL,IDR_MAINFRAME, L"Software\\WTL\\SPcontrols")
+
+       enum { IDD = IDD_MAINDLG };
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               return ::IsDialogMessage(m_hWnd, pMsg);
+       }
+
+       virtual BOOL OnIdle()
+       {
+               return FALSE;
+       }
+
+       void AppSave()
+       {
+               CAppInfo info;
+
+               // Save CapEdit text and selection 
+               CExpandCapEdit ece = GetDlgItem(IDC_CAPEDIT);
+               CString s;
+               int nLength = ece.GetWindowTextLength();
+               ece.GetWindowText(s.GetBufferSetLength(nLength + 1), nLength + 1);
+               s.ReleaseBuffer();
+               info.Save(s, L"Cap");
+
+               DWORD dwSel = ece.GetSel();
+               info.Save(dwSel, L"CapSel");
+
+               // Save SpinListBox text and selection 
+               CSpinListBox slb = GetDlgItem(IDC_LISTBOX);
+               int iSel = slb.GetCurSel();
+               info.Save(iSel, L"Spin");
+               
+               // Save ExpandListBox multiple selection 
+               CExpandListBox elb = GetDlgItem(IDC_LISTBOX2);
+               int n = elb.GetSelCount();
+               if (n)
+               {
+                       int *aiSel = new int[n];
+                       elb.GetSelItems(n, aiSel);
+                       info.Save( n, (int&)*aiSel, L"MultSel");
+                       delete[] aiSel;
+               }
+               info.Save( n, L"Mult");
+
+               // Save ExpandEdit text and selection 
+               CExpandEdit eed= GetDlgItem(IDC_EDIT1);
+               nLength = eed.GetWindowTextLength();
+               eed.GetWindowText(s.GetBufferSetLength(nLength + 1), nLength + 1);
+               s.ReleaseBuffer();
+               info.Save(s, L"Ed");
+
+               dwSel = eed.GetSel();
+               info.Save(dwSel, L"EdSel");
+       }
+
+       BEGIN_MSG_MAP(CMainDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               CHAIN_MSG_MAP(CAppStdDialogImpl<CMainDlg>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               // set icons
+               HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
+               SetIcon(hIcon, TRUE);
+               HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
+                       IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+               SetIcon(hIconSmall, FALSE);
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop(); 
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               // create MenuBar
+               HWND hMenuBar = AtlCreateMenuBar(m_hWnd, ATL_IDM_MENU_DONECANCEL);
+               ATLASSERT(hMenuBar != NULL);
+
+               // Application state initialization/restoration
+               CAppInfo info;
+
+               // CapEdit restoration or initialization
+               CExpandCapEdit ece = GetDlgItem(IDC_CAPEDIT);
+               CString s = L"capedit controls are not emulated with EVC 4 emulator.";
+               info.Restore(s, L"Cap");
+               ece.SetWindowText(s);
+
+               DWORD dwSel = 0;
+               info.Restore(dwSel, L"CapSel");
+               ece.SetSel(dwSel);
+               ece.SetFocus();
+
+
+               // SpinListBox initialization
+               CSpinListBox slb= GetDlgItem(IDC_LISTBOX);
+               slb.AddString(L"Spin choice 1");
+               slb.AddString(L"Spin choice 2");
+               slb.AddString(L"Spin choice 3");
+               // SpinListBox control restoration
+               int iSel = 0;
+               info.Restore(iSel, L"Spin");
+               slb.SetCurSel(iSel);
+
+               // Multiple choice ExpandListBox initialization
+               CExpandListBox elb= GetDlgItem(IDC_LISTBOX2);
+               elb.AddString(L"Multiple choice 1");
+               elb.AddString(L"Multiple choice 2");
+               elb.AddString(L"Multiple choice 3");
+               // Multiple choice ExpandListBox restoration
+               int n = 0;
+               info.Restore( n, L"Mult");
+               if (n)
+               {
+                       int *aiSel = new int[n];
+                       info.Restore( n, (int&)*aiSel, L"MultSel");
+                       for( int i = 0 ; i < n; i++)
+                               elb.SetSel(aiSel[i]);
+                       delete[] aiSel;
+               }
+
+               // ExpandEdit restoration or initialization
+               CExpandEdit eed= GetDlgItem(IDC_EDIT1);
+               s = L"What more do you want?";
+               info.Restore(s, L"Ed");
+               eed.SetWindowText(s);
+               dwSel = 0;
+               info.Restore(dwSel, L"EdSel");
+               eed.SetSel(dwSel);
+
+               return bHandled = FALSE;
+       }
+
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CStdSimpleDialog<IDD_ABOUTBOX> dlg;
+               dlg.DoModal();
+               return 0;
+       }
+
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // !defined(_MAINDLG_H_)
diff --git a/include/WTL/Samples/SPControls/res/SPcontrols.ico b/include/WTL/Samples/SPControls/res/SPcontrols.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/Samples/SPControls/res/SPcontrols.ico differ
diff --git a/include/WTL/Samples/SPControls/resource.h b/include/WTL/Samples/SPControls/resource.h
new file mode 100644 (file)
index 0000000..1990de3
--- /dev/null
@@ -0,0 +1,22 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by SPcontrols.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDD_MAINDLG                     129
+#define IDC_LISTBOX                     1000
+#define IDC_LISTBOX2                    1001
+#define IDC_EDIT1                       1002
+#define IDC_CAPEDIT                     1003
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        203
+#define _APS_NEXT_COMMAND_VALUE         32780
+#define _APS_NEXT_CONTROL_VALUE         1005
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/SPControls/stdafx.cpp b/include/WTL/Samples/SPControls/stdafx.cpp
new file mode 100644 (file)
index 0000000..5510c59
--- /dev/null
@@ -0,0 +1,6 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     SPcontrols.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
diff --git a/include/WTL/Samples/SPControls/stdafx.h b/include/WTL/Samples/SPControls/stdafx.h
new file mode 100644 (file)
index 0000000..29e2cc3
--- /dev/null
@@ -0,0 +1,19 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+// Change these values to use different versions
+#define WINVER         0x0420
+
+#include <atlbase.h>
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#include <atlwin.h>
+
+#include <aygshell.h>
+#include <tpcshell.h>
+#pragma comment(lib, "aygshell.lib")
+
diff --git a/include/WTL/Samples/TabBrowser/AboutDlg.h b/include/WTL/Samples/TabBrowser/AboutDlg.h
new file mode 100644 (file)
index 0000000..90e1dda
--- /dev/null
@@ -0,0 +1,29 @@
+// aboutdlg.h : interface of the CAboutDlg class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CAboutDlg : public CDialogImpl<CAboutDlg>
+{
+public:
+       enum { IDD = IDD_ABOUTBOX };
+
+       BEGIN_MSG_MAP(CAboutDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+               return TRUE;
+       }
+
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/TabBrowser/AddressCombo.h b/include/WTL/Samples/TabBrowser/AddressCombo.h
new file mode 100644 (file)
index 0000000..93e8599
--- /dev/null
@@ -0,0 +1,115 @@
+// AddressCombo.h - CAddressComboBox class
+
+#pragma once
+
+#define WM_COMBOMOUSEACTIVATE   (WM_APP + 10)
+
+
+class CAddressComboBox : public CWindowImpl<CAddressComboBox, CComboBoxEx>
+{
+public:
+       DECLARE_WND_SUPERCLASS(_T("TabBrowser_AddressComboBox"), CComboBoxEx::GetWndClassName())
+
+       enum
+       {
+               m_cxGap = 2,
+               m_cxMinDropWidth = 200
+       };
+
+       CComboBox m_cb;
+       CToolBarCtrl m_tb;
+       SIZE m_sizeTB;
+
+       BEGIN_MSG_MAP(CAddressComboBox)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
+               MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
+               NOTIFY_CODE_HANDLER(TTN_GETDISPINFO, OnToolTipText)
+               MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               // let the combo box initialize itself
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+               if(lRet != -1)
+               {
+                       // adjust the drop-down width
+                       m_cb = GetComboCtrl();
+                       m_cb.SetDroppedWidth(m_cxMinDropWidth);
+
+                       // create a toolbar for the GO button
+                       m_tb = CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(m_hWnd, IDR_GO, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST);
+
+                       RECT rect;
+                       m_tb.GetItemRect(0, &rect);
+                       m_sizeTB.cx = rect.right;
+                       m_sizeTB.cy = rect.bottom;
+               }
+
+               return lRet;
+       }
+
+       LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               CDCHandle dc = (HDC)wParam;
+               CWindow wndParent = GetParent();
+
+               // Forward this to the parent window, rebar bands are transparent
+               POINT pt = { 0, 0 };
+               MapWindowPoints(wndParent, &pt, 1);
+               dc.OffsetWindowOrg(pt.x, pt.y, &pt);
+               LRESULT lRet = wndParent.SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
+               dc.SetWindowOrg(pt.x, pt.y);
+
+               bHandled = (lRet != 0);
+               return lRet;
+       }
+
+       LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if(m_tb.m_hWnd == NULL)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               // copy the WINDOWPOS struct and adjust for the GO button
+               WINDOWPOS wp = *(LPWINDOWPOS)lParam;
+               wp.cx -= m_sizeTB.cx + m_cxGap;
+               LRESULT lRet = DefWindowProc(uMsg, wParam, (LPARAM)&wp);
+
+               // paint below the GO button
+               RECT rcGo = { wp.cx, 0, wp.cx + m_sizeTB.cx + m_cxGap, wp.cy };
+               InvalidateRect(&rcGo);
+
+               // center the GO button relative to the combo box
+               RECT rcCombo;
+               m_cb.GetWindowRect(&rcCombo);
+               int y = (rcCombo.bottom - rcCombo.top - m_sizeTB.cy) / 2;
+
+               // position the GO button on the right
+               m_tb.SetWindowPos(NULL, wp.cx + m_cxGap, y, m_sizeTB.cx, m_sizeTB.cy, SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
+
+               return lRet;
+       }
+
+       LRESULT OnToolTipText(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               if(idCtrl == ID_GO)
+                       SendMessage(GetParent(), WM_NOTIFY, idCtrl, (LPARAM)pnmh);
+               else
+                       bHandled = FALSE;
+
+               return 0;
+       }
+
+       LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               SendMessage(GetTopLevelParent(), WM_COMBOMOUSEACTIVATE, 0, 0L);
+
+               return lRet;
+       }
+};
diff --git a/include/WTL/Samples/TabBrowser/BrowserView.h b/include/WTL/Samples/TabBrowser/BrowserView.h
new file mode 100644 (file)
index 0000000..8e7b633
--- /dev/null
@@ -0,0 +1,178 @@
+// BrowserView.h : interface of the CBrowserView class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <exdispid.h>
+
+const int _nDispatchID = 1;
+
+#define WM_BROWSERTITLECHANGE        (WM_APP)
+#define WM_BROWSERDOCUMENTCOMPLETE   (WM_APP + 1)
+#define WM_BROWSERSTATUSTEXTCHANGE   (WM_APP + 2)
+
+
+class CBrowserView : public CWindowImpl<CBrowserView, CAxWindow>, 
+               public IDispEventSimpleImpl<_nDispatchID, CBrowserView, &DIID_DWebBrowserEvents2>
+{
+public:
+       DECLARE_WND_SUPERCLASS(_T("TabBrowser_TabPageWindow"), CAxWindow::GetWndClassName())
+
+       // IDispatch events function info
+       static _ATL_FUNC_INFO DocumentComplete2_Info;
+       static _ATL_FUNC_INFO TitleChange_Info;
+       static _ATL_FUNC_INFO StatusTextChange_Info;
+       static _ATL_FUNC_INFO CommandStateChange_Info;
+
+       bool m_bCanGoBack;
+       bool m_bCanGoForward;
+
+
+       CBrowserView() : m_bCanGoBack(false), m_bCanGoForward(false)
+       {
+       }
+
+       BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
+                  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
+                       return FALSE;
+
+               BOOL bRet = FALSE;
+               // give HTML page a chance to translate this message
+               if(pMsg->hwnd == m_hWnd || IsChild(pMsg->hwnd))
+                       bRet = (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
+
+               return bRet;
+       }
+
+       virtual void OnFinalMessage(HWND /*hWnd*/)
+       {
+               delete this;
+       }
+
+       void SetFocusToHTML()
+       {
+               CComPtr<IWebBrowser2> spWebBrowser;
+               HRESULT hRet = QueryControl(IID_IWebBrowser2, (void**)&spWebBrowser);
+               if(SUCCEEDED(hRet) && spWebBrowser != NULL)
+               {
+                       CComPtr<IDispatch> spDocument;
+                       hRet = spWebBrowser->get_Document(&spDocument);
+                       if(SUCCEEDED(hRet) && spDocument != NULL)
+                       {
+                               CComQIPtr<IHTMLDocument2> spHtmlDoc = spDocument;
+                               if(spHtmlDoc != NULL)
+                               {
+                                       CComPtr<IHTMLWindow2> spParentWindow;
+                                       hRet = spHtmlDoc->get_parentWindow(&spParentWindow);
+                                       if(spParentWindow != NULL)
+                                               spParentWindow->focus();
+                               }
+                       }
+               }
+       }
+
+// Event map and handlers
+#ifdef _VC80X
+  #pragma warning(disable:4867)
+#endif
+       BEGIN_SINK_MAP(CBrowserView)
+               SINK_ENTRY_INFO(_nDispatchID, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnEventDocumentComplete, &DocumentComplete2_Info)
+               SINK_ENTRY_INFO(_nDispatchID, DIID_DWebBrowserEvents2, DISPID_TITLECHANGE, OnEventTitleChange, &TitleChange_Info)
+               SINK_ENTRY_INFO(_nDispatchID, DIID_DWebBrowserEvents2, DISPID_STATUSTEXTCHANGE, OnEventStatusTextChange, &StatusTextChange_Info)
+               SINK_ENTRY_INFO(_nDispatchID, DIID_DWebBrowserEvents2, DISPID_COMMANDSTATECHANGE, OnEventCommandStateChange, &CommandStateChange_Info)
+       END_SINK_MAP()
+#ifdef _VC80X
+  #pragma warning(default:4867)
+#endif
+
+       void __stdcall OnEventDocumentComplete(IDispatch* /*pDisp*/, VARIANT* URL)
+       {
+               // Send message to the main frame
+               ATLASSERT(V_VT(URL) == VT_BSTR);
+               USES_CONVERSION;
+               SendMessage(GetTopLevelWindow(), WM_BROWSERDOCUMENTCOMPLETE, (WPARAM)m_hWnd, (LPARAM)OLE2T(URL->bstrVal));
+
+               SetFocusToHTML();
+       }
+
+       void __stdcall OnEventTitleChange(BSTR Text)
+       {
+               USES_CONVERSION;
+               SendMessage(GetTopLevelWindow(), WM_BROWSERTITLECHANGE, (WPARAM)m_hWnd, (LPARAM)OLE2CT(Text));
+       }
+
+       void __stdcall OnEventStatusTextChange(BSTR Text)
+       {
+               USES_CONVERSION;
+               SendMessage(GetTopLevelWindow(), WM_BROWSERSTATUSTEXTCHANGE, (WPARAM)m_hWnd, (LPARAM)OLE2CT(Text));
+       }
+
+       void __stdcall OnEventCommandStateChange(long Command, VARIANT_BOOL Enable)
+       {
+               if(Command == CSC_NAVIGATEBACK)
+                       m_bCanGoBack = (Enable != VARIANT_FALSE);
+               else if(Command == CSC_NAVIGATEFORWARD)
+                       m_bCanGoForward = (Enable != VARIANT_FALSE);
+       }
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CBrowserView)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+               // Connect events
+               CComPtr<IWebBrowser2> spWebBrowser2;
+               HRESULT hRet = QueryControl(IID_IWebBrowser2, (void**)&spWebBrowser2);
+               if(SUCCEEDED(hRet))
+               {
+                       if(FAILED(DispEventAdvise(spWebBrowser2, &DIID_DWebBrowserEvents2)))
+                               ATLASSERT(FALSE);
+               }
+
+               // Set host flag to indicate that we handle themes
+               CComPtr<IAxWinAmbientDispatch> spHost;
+               hRet = QueryHost(IID_IAxWinAmbientDispatch, (void**)&spHost);
+               if(SUCCEEDED(hRet))
+               {
+                       const DWORD _DOCHOSTUIFLAG_THEME = 0x40000;
+                       hRet = spHost->put_DocHostFlags(DOCHOSTUIFLAG_NO3DBORDER | _DOCHOSTUIFLAG_THEME);
+                       ATLASSERT(SUCCEEDED(hRet));
+               }
+
+               return lRet;
+       }
+       
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               // Disconnect events
+               CComPtr<IWebBrowser2> spWebBrowser2;
+               HRESULT hRet = QueryControl(IID_IWebBrowser2, (void**)&spWebBrowser2);
+               if(SUCCEEDED(hRet))
+                       DispEventUnadvise(spWebBrowser2, &DIID_DWebBrowserEvents2);
+
+               bHandled=FALSE;
+               return 1;
+       }
+
+       LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+               SetFocusToHTML();
+
+               return lRet;
+       }
+};
+
+__declspec(selectany) _ATL_FUNC_INFO CBrowserView::DocumentComplete2_Info = { CC_STDCALL, VT_EMPTY, 2, { VT_DISPATCH, VT_BYREF | VT_VARIANT } };
+__declspec(selectany) _ATL_FUNC_INFO CBrowserView::TitleChange_Info = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };
+__declspec(selectany) _ATL_FUNC_INFO CBrowserView::StatusTextChange_Info = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };
+__declspec(selectany) _ATL_FUNC_INFO CBrowserView::CommandStateChange_Info = { CC_STDCALL, VT_EMPTY, 2, { VT_I4, VT_BOOL } };
diff --git a/include/WTL/Samples/TabBrowser/CustomTabView.h b/include/WTL/Samples/TabBrowser/CustomTabView.h
new file mode 100644 (file)
index 0000000..23a5b0f
--- /dev/null
@@ -0,0 +1,90 @@
+// CustomTabView.h - CCustomTabView class
+
+#pragma once
+
+
+class CCustomTabView : public CTabViewImpl<CCustomTabView>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("TabBrowser_CustomTabView"), 0, COLOR_APPWORKSPACE)
+
+       CToolBarCtrl m_wndTB;
+       int m_cxTB;
+
+       CString m_strTooltip;
+
+       CCustomTabView() : m_cxTB(0)
+       { }
+
+// Overrideables - add a toolbar next to the tab control
+       bool CreateTabControl()
+       {
+               bool bRet = CTabViewImpl<CCustomTabView>::CreateTabControl();
+               if(bRet)
+               {
+                       DWORD dwStyle = (ATL_SIMPLE_TOOLBAR_STYLE | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN) & ~WS_VISIBLE;
+                       m_wndTB = AtlCreateSimpleToolBar(m_hWnd, IDR_TABTOOLBAR, FALSE, dwStyle);
+
+                       // BLOCK: set drop-down style for the window button
+                       {
+                               TBBUTTONINFO tbbi;
+                               tbbi.cbSize = sizeof(tbbi);
+                               tbbi.dwMask = TBIF_STYLE;
+                               tbbi.fsStyle = BTNS_BUTTON | BTNS_WHOLEDROPDOWN;
+                               m_wndTB.SetButtonInfo(ID_WINDOW_SHOW_VIEWS, &tbbi);
+                       }
+
+                       RECT rect = { 0 };
+                       m_wndTB.GetItemRect(m_wndTB.GetButtonCount() - 1, &rect);
+                       m_cxTB = rect.right;
+
+                       CToolTipCtrl tt = m_tab.GetTooltips();
+                       tt.SetMaxTipWidth(0);   // we just want to use \n for a new line
+               }
+
+               return bRet;
+       }
+
+       void UpdateLayout()
+       {
+               RECT rect;
+               GetClientRect(&rect);
+
+               if(m_tab.IsWindow() && m_tab.IsWindowVisible())
+                       m_tab.SetWindowPos(NULL, 0, 0, rect.right - rect.left - m_cxTB, m_cyTabHeight, SWP_NOZORDER);
+
+               if(m_wndTB.IsWindow() && m_tab.IsWindowVisible())
+                       m_wndTB.SetWindowPos(NULL, rect.right - m_cxTB, 0, m_cxTB, m_cyTabHeight, SWP_NOZORDER);
+
+               if(m_nActivePage != -1)
+                       ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, m_cyTabHeight, rect.right - rect.left, rect.bottom - rect.top - m_cyTabHeight, SWP_NOZORDER);
+       }
+
+       void ShowTabControl(bool bShow)
+       {
+               m_tab.ShowWindow(bShow ? SW_SHOWNOACTIVATE : SW_HIDE);
+               m_wndTB.ShowWindow(bShow ? SW_SHOWNOACTIVATE : SW_HIDE);
+       }
+
+       void UpdateTooltipText(LPNMTTDISPINFO pTTDI)
+       {
+               ATLASSERT(pTTDI != NULL);
+
+               m_strTooltip = GetPageTitle(pTTDI->hdr.idFrom);
+
+               CAxWindow wnd = GetPageHWND(pTTDI->hdr.idFrom);
+               CComPtr<IWebBrowser2> spWebBrowser;
+               HRESULT hRet = wnd.QueryControl(IID_IWebBrowser2, (void**)&spWebBrowser);
+               hRet;   // avoid level 4 warning
+               ATLASSERT(SUCCEEDED(hRet));
+               if(spWebBrowser != NULL)
+               {
+                       BSTR bstrURL;
+                       spWebBrowser->get_LocationURL(&bstrURL);
+                       m_strTooltip += _T("\n");
+                       m_strTooltip += bstrURL;
+               }
+
+               pTTDI->lpszText = (LPTSTR)(LPCTSTR)m_strTooltip;
+       }
+};
diff --git a/include/WTL/Samples/TabBrowser/MainFrm.h b/include/WTL/Samples/TabBrowser/MainFrm.h
new file mode 100644 (file)
index 0000000..ed37406
--- /dev/null
@@ -0,0 +1,763 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#define WINDOW_MENU_POSITION   3
+
+
+class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>,
+               public CMessageFilter, public CIdleHandler
+{
+public:
+       DECLARE_FRAME_WND_CLASS(_T("TabBrowser_MainFrame"), IDR_MAINFRAME)
+
+// Data members
+       CCommandBarCtrl m_CmdBar;
+       CCustomTabView m_view;
+       CAddressComboBox m_cb;
+
+       CString m_strHomePage;
+
+// CMessageFilter
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               if(ProcessComboReturnKey(pMsg) != FALSE)
+                       return TRUE;
+
+               if(m_view.PreTranslateMessage(pMsg) != FALSE)
+                       return TRUE;
+
+               return CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg);
+       }
+
+       BOOL ProcessComboReturnKey(MSG* pMsg)
+       {
+               BOOL bRet = FALSE;
+
+               if(IsPageActive() && (pMsg->hwnd == m_cb.m_hWnd || ::IsChild(m_cb.m_hWnd, pMsg->hwnd)))
+               {
+                       if((pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN) && pMsg->wParam == VK_RETURN)
+                       {
+                               CString str;
+                               int nLen = m_cb.GetWindowTextLength();
+                               m_cb.GetWindowText(str.GetBuffer(nLen), nLen + 1);
+                               str.ReleaseBuffer();
+                               str.TrimLeft();
+                               str.TrimRight();
+
+                               if(!str.IsEmpty())
+                               {
+                                       if(pMsg->message == WM_SYSKEYDOWN)
+                                       {
+                                               OpenPage(str, true);
+                                       }
+                                       if(GetKeyState(VK_CONTROL) < 0)
+                                       {
+                                               CString strExp;
+                                               strExp.Format(_T("http://www.%s.com"), (LPCTSTR)str);
+
+                                               m_cb.SetWindowText(strExp);
+                                               OpenPage(strExp, false);
+                                       }
+                                       else
+                                       {
+                                               OpenPage(str, false);
+                                       }
+                               }
+
+                               bRet = TRUE;
+                       }
+               }
+
+               return bRet;
+       }
+
+// CIdleHandler
+       virtual BOOL OnIdle()
+       {
+               bool bActive = IsPageActive();
+
+               bool bCanGoBack = false;
+               bool bCanGoForward = false;
+
+               if(bActive)
+               {
+                       CBrowserView* pView = (CBrowserView*)m_view.GetPageData(m_view.GetActivePage());
+                       bCanGoBack = pView->m_bCanGoBack;
+                       bCanGoForward = pView->m_bCanGoForward;
+               }
+
+               UIEnable(ID_BROWSER_BACK, bActive && bCanGoBack);
+               UIEnable(ID_BROWSER_FORWARD, bActive && bCanGoForward);
+               UIEnable(ID_BROWSER_STOP, bActive);
+               UIEnable(ID_BROWSER_REFRESH, bActive);
+               UIEnable(ID_BROWSER_HOME, bActive);
+               UIEnable(ID_BROWSER_SEARCH, bActive);
+
+               UIEnable(ID_WINDOW_CLOSE, bActive);
+               UIEnable(ID_WINDOW_CLOSE_ALL, bActive);
+
+               UIEnable(ID_WINDOW_SHOW_VIEWS, bActive);
+
+               UIEnable(ID_GO, bActive);
+
+               UIUpdateToolBar();
+
+               m_cb.EnableWindow(bActive ? TRUE : FALSE);
+
+               return FALSE;
+       }
+
+// Methods
+       bool GetHomePage()
+       {
+               LPCTSTR lpstrHomePageRegKey = _T("Software\\Microsoft\\Internet Explorer\\Main");
+               LPCTSTR lpstrHomePageRegValue = _T("Start Page");
+
+               ATL::CRegKey rk;
+               LONG lRet = rk.Open(HKEY_CURRENT_USER, lpstrHomePageRegKey);
+               ATLASSERT(lRet == ERROR_SUCCESS);
+               if(lRet != ERROR_SUCCESS)
+                       return false;
+
+#if (_ATL_VER >= 0x0700)
+               ULONG ulLength = 0;
+               lRet = rk.QueryStringValue(lpstrHomePageRegValue, NULL, &ulLength);
+               if(lRet == ERROR_SUCCESS)
+                       lRet = rk.QueryStringValue(lpstrHomePageRegValue, m_strHomePage.GetBuffer(ulLength), &ulLength);
+#else
+               DWORD dwLength = 0;
+               lRet = rk.QueryValue(NULL, lpstrHomePageRegValue, &dwLength);
+               if(lRet == ERROR_SUCCESS)
+                       lRet = rk.QueryValue(m_strHomePage.GetBuffer(dwLength / sizeof(TCHAR)), lpstrHomePageRegValue, &dwLength);
+#endif
+               ATLASSERT(lRet == ERROR_SUCCESS);
+               m_strHomePage.ReleaseBuffer();
+
+               return (lRet == ERROR_SUCCESS);
+       }
+
+       bool IsPageActive() const
+       {
+               return (m_view.GetActivePage() != -1);
+       }
+
+       IWebBrowser2* GetBrowser(int nPage) const
+       {
+               CAxWindow wnd = m_view.GetPageHWND(nPage);
+
+               CComPtr<IWebBrowser2> spWebBrowser;
+               HRESULT hRet = wnd.QueryControl(IID_IWebBrowser2, (void**)&spWebBrowser);
+               hRet;   // avoid level 4 warning
+               ATLASSERT(SUCCEEDED(hRet));
+
+               return spWebBrowser;
+       }
+
+       void OpenPage(LPCTSTR lpstrURL, bool bNewTab)
+       {
+               CString strLoading;
+               strLoading.LoadString(IDS_LOADING);
+
+               bool bSuccess = false;
+
+               if(bNewTab)
+               {
+                       CBrowserView* pView = new CBrowserView;
+                       pView->Create(m_view, rcDefault, lpstrURL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL);
+                       if(pView->IsWindow())
+                               bSuccess = m_view.AddPage(pView->m_hWnd, strLoading, 0, pView);
+               }
+               else
+               {
+                       m_view.SetPageTitle(m_view.GetActivePage(), strLoading);
+
+                       CComPtr<IWebBrowser2> spWebBrowser = GetBrowser(m_view.GetActivePage());
+                       if(spWebBrowser != NULL)
+                       {
+                               CComVariant vtURL(lpstrURL);
+                               CComVariant vt;
+                               HRESULT hRet = spWebBrowser->Navigate2(&vtURL, &vt, &vt, &vt, &vt);
+                               bSuccess = SUCCEEDED(hRet);
+                       }
+               }
+
+               if(!bSuccess)
+               {
+                       CString strError;
+                       strError.LoadString(IDS_OPEN_ERROR);
+                       strError += lpstrURL;
+                       CString strTitle;
+                       strTitle.LoadString(IDR_MAINFRAME);
+                       MessageBox(strError, strTitle, MB_OK | MB_ICONERROR);
+               }
+       }
+
+       void BuildLinksToolbar(HWND hWndToolBar)
+       {
+               CToolBarCtrl tb = hWndToolBar;
+
+               tb.SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS);
+
+               // add links buttons
+               CString strTitle;
+               strTitle.LoadString(ID_LINKS_MICROSOFT);
+               tb.AddButton(ID_LINKS_MICROSOFT, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
+               strTitle.LoadString(ID_LINKS_MSDN);
+               tb.AddButton(ID_LINKS_MSDN, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
+               strTitle.LoadString(ID_LINKS_LIVE);
+               tb.AddButton(ID_LINKS_LIVE, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
+               strTitle.LoadString(ID_LINKS_UPDATE);
+               tb.AddButton(ID_LINKS_UPDATE, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
+               strTitle.LoadString(ID_LINKS_WTL);
+               tb.AddButton(ID_LINKS_WTL, BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, TBSTATE_ENABLED, 0, strTitle, 0);
+
+               // delete initial button (not used)
+               tb.DeleteButton(0);
+       }
+
+       void DeactivateHTMLPage()
+       {
+               if(IsPageActive())
+               {
+                       CAxWindow wnd = m_view.GetPageHWND(m_view.GetActivePage());
+                       CComPtr<IOleInPlaceObject> spInPlaceObject;
+                       HRESULT hRet = wnd.QueryControl(IID_IOleInPlaceObject, (void**)&spInPlaceObject);
+                       ATLASSERT(SUCCEEDED(hRet));
+                       if(spInPlaceObject != NULL)
+                       {
+                               hRet = spInPlaceObject->UIDeactivate();
+                               ATLASSERT(SUCCEEDED(hRet));
+                       }
+               }
+       }
+
+// Update UI map
+       BEGIN_UPDATE_UI_MAP(CMainFrame)
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_ADDRESS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_LINKS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_LOCK_TOOLBARS, UPDUI_MENUPOPUP)
+
+               UPDATE_ELEMENT(ID_BROWSER_BACK, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_BROWSER_FORWARD, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_BROWSER_STOP, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_BROWSER_REFRESH, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_BROWSER_HOME, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_BROWSER_SEARCH, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
+
+               UPDATE_ELEMENT(ID_GO, UPDUI_TOOLBAR)
+
+               UPDATE_ELEMENT(ID_WINDOW_CLOSE, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_WINDOW_CLOSE_ALL, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
+       END_UPDATE_UI_MAP()
+
+// Message map and handlers
+       BEGIN_MSG_MAP(CMainFrame)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
+
+               MESSAGE_HANDLER(WM_BROWSERTITLECHANGE, OnBrowserTitleChange)
+               MESSAGE_HANDLER(WM_BROWSERDOCUMENTCOMPLETE, OnBrowserDocumentComplete)
+               MESSAGE_HANDLER(WM_BROWSERSTATUSTEXTCHANGE, OnBrowserStatusTextChange)
+
+               MESSAGE_HANDLER(WM_COMBOMOUSEACTIVATE, OnComboMouseActivate)
+
+               CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
+
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+               COMMAND_ID_HANDLER(ID_FILE_OPEN, OnFileOpen)
+
+               COMMAND_ID_HANDLER(ID_BROWSER_BACK, OnBrowserNavigate)
+               COMMAND_ID_HANDLER(ID_BROWSER_FORWARD, OnBrowserNavigate)
+               COMMAND_ID_HANDLER(ID_BROWSER_STOP, OnBrowserNavigate)
+               COMMAND_ID_HANDLER(ID_BROWSER_REFRESH, OnBrowserNavigate)
+               COMMAND_ID_HANDLER(ID_BROWSER_HOME, OnBrowserNavigate)
+               COMMAND_ID_HANDLER(ID_BROWSER_SEARCH, OnBrowserNavigate)
+
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+               COMMAND_ID_HANDLER(ID_VIEW_ADDRESS_BAR, OnViewAddressBar)
+               COMMAND_ID_HANDLER(ID_VIEW_LINKS_BAR, OnViewLinksBar)
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+               COMMAND_ID_HANDLER(ID_VIEW_LOCK_TOOLBARS, OnViewLockToolbars)
+
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose)
+               COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll)
+               COMMAND_ID_HANDLER(ID_NEXT_PANE, OnNextPrevPane)
+               COMMAND_ID_HANDLER(ID_PREV_PANE, OnNextPrevPane)
+
+               COMMAND_ID_HANDLER(ID_LINKS_MICROSOFT, OnLinks)
+               COMMAND_ID_HANDLER(ID_LINKS_MSDN, OnLinks)
+               COMMAND_ID_HANDLER(ID_LINKS_LIVE, OnLinks)
+               COMMAND_ID_HANDLER(ID_LINKS_UPDATE, OnLinks)
+               COMMAND_ID_HANDLER(ID_LINKS_WTL, OnLinks)
+
+               COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
+               COMMAND_ID_HANDLER(ID_WINDOW_SHOWTABLIST, OnShowWindows)
+
+               NOTIFY_CODE_HANDLER(TBVN_PAGEACTIVATED, OnTabViewPageActivated)
+               NOTIFY_CODE_HANDLER(TBVN_CONTEXTMENU, OnTabViewContextMenu)
+
+               NOTIFY_CODE_HANDLER(TBN_DROPDOWN, OnTBDropDown)
+               COMMAND_ID_HANDLER(ID_GO, OnGo)
+
+               CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               // create command bar window
+               HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+               // attach menu
+               m_CmdBar.AttachMenu(GetMenu());
+               // load command bar images
+               m_CmdBar.SetImageMaskColor(RGB(255, 0, 255));
+               m_CmdBar.LoadImages(IDR_MAINFRAME);
+               m_CmdBar.LoadImages(IDR_TABTOOLBAR);
+               // remove old menu
+               SetMenu(NULL);
+
+               // create toolbar
+               HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME_BIG, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+
+               // create rebar
+               CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+               AddSimpleReBarBand(hWndCmdBar);
+               AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+
+               // create address bar combo
+               RECT rcCombo = { 0, 0, 1, 300 };
+               m_cb.Create(m_hWnd, rcCombo, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBS_DROPDOWN | CBS_AUTOHSCROLL);
+               m_cb.SetFont(AtlGetDefaultGuiFont());
+
+               CString strAddress;
+               strAddress.LoadString(IDS_ADDRESS);
+               AddSimpleReBarBand(m_cb, strAddress, FALSE, 10000);
+               SizeSimpleReBarBands();
+
+               // create links bar
+               HWND hWndToolBarLinks = CreateSimpleToolBarCtrl(m_hWnd, IDB_PAGEIMAGE, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST);
+               BuildLinksToolbar(hWndToolBarLinks);
+               CString strLinks;
+               strLinks.LoadString(IDS_LINKS);
+               AddSimpleReBarBand(hWndToolBarLinks, strLinks);
+
+               CReBarCtrl rebar = m_hWndToolBar;
+               rebar.LockBands(true);
+
+               CreateSimpleStatusBar();
+
+               // create tab view
+               m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+               m_view.SetTitleBarWindow(m_hWnd);
+
+               // Set up update UI stuff
+               UIAddToolBar(hWndToolBar);
+               UIAddToolBar(m_cb.m_tb);
+
+               UISetCheck(ID_VIEW_TOOLBAR, 1);
+               UISetCheck(ID_VIEW_STATUS_BAR, 1);
+               UISetCheck(ID_VIEW_ADDRESS_BAR, 1);
+               UISetCheck(ID_VIEW_LINKS_BAR, 1);
+               UISetCheck(ID_VIEW_LOCK_TOOLBARS, 1);
+
+               UISetBlockAccelerators(true);
+
+               // register object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->AddMessageFilter(this);
+               pLoop->AddIdleHandler(this);
+
+               // set tab view image list
+               CImageList il;
+               il.CreateFromImage(IDB_PAGEIMAGE, 16, 1, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
+               m_view.SetImageList(il);
+
+               // srt up window menu
+               m_view.m_bWindowsMenuItem = true;
+               CMenuHandle menuMain = m_CmdBar.GetMenu();
+               m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));
+
+               // get home page address
+               bool bRet = GetHomePage();
+               if(!bRet)
+               {
+                       ATLTRACE(_T("TabBrowser: Can't get home page from the registry - using blank page\n"));
+                       m_strHomePage.LoadString(IDS_BLANK_URL);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               // unregister object for message filtering and idle updates
+               CMessageLoop* pLoop = _Module.GetMessageLoop();
+               ATLASSERT(pLoop != NULL);
+               pLoop->RemoveMessageFilter(this);
+               pLoop->RemoveIdleHandler(this);
+
+               bHandled = FALSE;
+               return 1;
+       }
+
+       LRESULT OnContextMenu(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if((HWND)wParam == m_hWndToolBar || ::IsChild(m_hWndToolBar, (HWND)wParam))
+               {
+                       POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+                       CMenu menu;
+                       menu.LoadMenu(IDR_TOOLBAR_MENU);
+                       CMenuHandle menuPopup = menu.GetSubMenu(0);
+                       m_CmdBar.TrackPopupMenu(menuPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y);
+               }
+               else
+               {
+                       bHandled = FALSE;
+               }
+
+               return 0;
+       }
+
+       LRESULT OnBrowserTitleChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               HWND hWnd = (HWND)wParam;
+               LPCTSTR lpstrTitle = (LPCTSTR)lParam;
+
+               CString strBlank;
+               strBlank.LoadString(IDS_BLANK_URL);
+               CString strBlankTitle;
+               if(lstrcmp(lpstrTitle, strBlank) == 0)
+               {
+                       strBlankTitle.LoadString(IDS_BLANK_TITLE);
+                       lpstrTitle = (LPCTSTR)strBlankTitle;
+               }
+
+               int nIndex = m_view.PageIndexFromHwnd(hWnd);
+               m_view.SetPageTitle(nIndex, lpstrTitle);
+
+               return 0;
+       }
+
+       LRESULT OnBrowserDocumentComplete(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LPCTSTR lpstrAddress = (LPCTSTR)lParam;
+               m_cb.SetWindowText(lpstrAddress);
+
+               if(m_cb.FindStringExact(-1, lpstrAddress) == CB_ERR)
+                       m_cb.AddItem(lpstrAddress, -1, -1, 0);
+
+               return 0;
+       }
+
+       LRESULT OnBrowserStatusTextChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               LPCTSTR lpstrText = (LPCTSTR)lParam;
+               CStatusBarCtrl sb = m_hWndStatusBar;
+               sb.SetText(ID_DEFAULT_PANE, lpstrText);
+
+               return 0;
+       }
+
+       LRESULT OnComboMouseActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               DeactivateHTMLPage();
+
+               return 0;
+       }
+
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               PostMessage(WM_CLOSE);
+               return 0;
+       }
+
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               OpenPage(m_strHomePage, true);
+
+               return 0;
+       }
+
+       LRESULT OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CString strURL;
+
+               int nActivePage = m_view.GetActivePage();
+               if(nActivePage != -1)
+               {
+                       CComPtr<IWebBrowser2> spWebBrowser = GetBrowser(nActivePage);
+                       ATLASSERT(spWebBrowser != NULL);
+                       BSTR bstrURL;
+                       spWebBrowser->get_LocationURL(&bstrURL);
+                       strURL = bstrURL;
+               }
+
+               COpenDlg dlg(strURL);
+               if(dlg.DoModal() != IDOK)
+                       return 0;
+
+               OpenPage(dlg.m_strURL, dlg.m_bNewTab);
+
+               return 0;
+       }
+
+       LRESULT OnBrowserNavigate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               int nActivePage = m_view.GetActivePage();
+               if(nActivePage != -1)
+               {
+                       CComPtr<IWebBrowser2> spWebBrowser = GetBrowser(nActivePage);
+                       ATLASSERT(spWebBrowser != NULL);
+                       HRESULT hRet = E_FAIL;
+                       switch(wID)
+                       {
+                       case ID_BROWSER_BACK:
+                               hRet = spWebBrowser->GoBack();
+                               break;
+                       case ID_BROWSER_FORWARD:
+                               hRet = spWebBrowser->GoForward();
+                               break;
+                       case ID_BROWSER_STOP:
+                               hRet = spWebBrowser->Stop();
+                               break;
+                       case ID_BROWSER_REFRESH:
+                               hRet = spWebBrowser->Refresh();
+                               break;
+                       case ID_BROWSER_HOME:
+                               hRet = spWebBrowser->GoHome();
+                               break;
+                       case ID_BROWSER_SEARCH:
+                               hRet = spWebBrowser->GoSearch();
+                               break;
+                       default:
+                               break;
+                       }
+                       ATLASSERT(SUCCEEDED(hRet));
+               }
+               else
+               {
+                       ::MessageBeep((UINT)-1);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               static BOOL bVisible = TRUE;    // initially visible
+               bVisible = !bVisible;
+               CReBarCtrl rebar = m_hWndToolBar;
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);       // toolbar is 2nd added band
+               rebar.ShowBand(nBandIndex, bVisible);
+               UISetCheck(ID_VIEW_TOOLBAR, bVisible);
+               UpdateLayout();
+
+               return 0;
+       }
+
+       LRESULT OnViewAddressBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               static BOOL bVisible = TRUE;    // initially visible
+               bVisible = !bVisible;
+               CReBarCtrl rebar = m_hWndToolBar;
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 2);       // address bar is 2nd added band
+               rebar.ShowBand(nBandIndex, bVisible);
+               UISetCheck(ID_VIEW_ADDRESS_BAR, bVisible);
+               UpdateLayout();
+
+               return 0;
+       }
+
+       LRESULT OnViewLinksBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               static BOOL bVisible = TRUE;    // initially visible
+               bVisible = !bVisible;
+               CReBarCtrl rebar = m_hWndToolBar;
+               int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 3);       // links bar is 3rd added band
+               rebar.ShowBand(nBandIndex, bVisible);
+               UISetCheck(ID_VIEW_LINKS_BAR, bVisible);
+               UpdateLayout();
+
+               return 0;
+       }
+
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
+               ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
+               UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
+               UpdateLayout();
+
+               return 0;
+       }
+
+       LRESULT OnViewLockToolbars(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               static bool bLock = true;       // initially locked
+               bLock = !bLock;
+               CReBarCtrl rebar = m_hWndToolBar;
+               rebar.LockBands(bLock);
+               UISetCheck(ID_VIEW_LOCK_TOOLBARS, bLock);
+
+               return 0;
+       }
+
+       LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CAboutDlg dlg;
+               dlg.DoModal();
+
+               return 0;
+       }
+
+       LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               int nActivePage = m_view.GetActivePage();
+               if(nActivePage != -1)
+                       m_view.RemovePage(nActivePage);
+               else
+                       ::MessageBeep((UINT)-1);
+
+               return 0;
+       }
+
+       LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               m_view.RemoveAllPages();
+
+               return 0;
+       }
+
+       LRESULT OnNextPrevPane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               // we have only two destinations, so there is no need to look at the direction
+               HWND hWndFocus = ::GetFocus();
+               if(IsPageActive() && (hWndFocus == m_cb.m_hWnd || ::IsChild(m_cb.m_hWnd, hWndFocus)))
+               {
+                       m_view.SetFocus();
+               }
+               else
+               {
+                       DeactivateHTMLPage();
+                       m_cb.SetFocus();
+               }
+
+               return 0;
+       }
+
+       LRESULT OnLinks(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               ATLASSERT(wID >= ID_LINKS_FIRST && wID <= ID_LINKS_LAST);
+
+               UINT nStringID = wID + (ID_LINKS_URL_FIRST - ID_LINKS_FIRST);
+               CString strURL;
+               strURL.LoadString(nStringID);
+               ATLASSERT(!strURL.IsEmpty());
+
+               OpenPage(strURL, !IsPageActive());
+
+               return 0;
+       }
+
+       LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               int nPage = wID - ID_WINDOW_TABFIRST;
+               m_view.SetActivePage(nPage);
+
+               return 0;
+       }
+
+       LRESULT OnShowWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CWindowsDlg dlg(&m_view);
+               dlg.DoModal(m_hWnd);
+
+               return 0;
+       }
+
+       LRESULT OnTabViewPageActivated(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               if(pnmh->idFrom != -1)
+               {
+                       CComPtr<IWebBrowser2> spWebBrowser = GetBrowser(pnmh->idFrom);
+                       ATLASSERT(spWebBrowser != NULL);
+                       BSTR bstrURL;
+                       HRESULT hRet = spWebBrowser->get_LocationURL(&bstrURL);
+                       hRet;   // avoid level 4 warning
+                       ATLASSERT(SUCCEEDED(hRet));
+
+                       USES_CONVERSION;
+                       m_cb.SetWindowText(OLE2T(bstrURL));
+               }
+               else
+               {
+                       m_cb.SetWindowText(_T(""));
+               }
+
+               return 0;
+       }
+
+       LRESULT OnTabViewContextMenu(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+       {
+               LPTBVCONTEXTMENUINFO lpcmi = (LPTBVCONTEXTMENUINFO)pnmh;
+               CMenuHandle menuMain = m_CmdBar.GetMenu();
+               CMenuHandle menuPopup = menuMain.GetSubMenu(WINDOW_MENU_POSITION);      // Window sub menu
+               int nRet = (int)m_CmdBar.TrackPopupMenu(menuPopup, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_RIGHTBUTTON, lpcmi->pt.x, lpcmi->pt.y);
+               if(nRet == ID_WINDOW_CLOSE)
+                       m_view.RemovePage(pnmh->idFrom);
+               else
+                       SendMessage(WM_COMMAND, MAKEWPARAM(nRet, 0));
+
+               return 0;
+       }
+
+       LRESULT OnTBDropDown(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
+       {
+               LPNMTOOLBAR lpTB = (LPNMTOOLBAR)pnmh;
+
+               if(lpTB->iItem != ID_WINDOW_SHOW_VIEWS) // something else
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               CToolBarCtrl wndToolBar = pnmh->hwndFrom;
+               int nIndex = wndToolBar.CommandToIndex(ID_WINDOW_SHOW_VIEWS);
+               RECT rect;
+               wndToolBar.GetItemRect(nIndex, &rect);
+               wndToolBar.ClientToScreen(&rect);
+
+               CMenu menu;
+               menu.CreatePopupMenu();
+
+               m_view.BuildWindowMenu(menu);
+
+               m_CmdBar.TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL, rect.left, rect.bottom);
+
+               return TBDDRET_DEFAULT;
+       }
+
+       LRESULT OnGo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CString str;
+               int nLen = m_cb.GetWindowTextLength();
+               m_cb.GetWindowText(str.GetBuffer(nLen), nLen + 1);
+               str.ReleaseBuffer();
+
+               str.TrimLeft();
+               str.TrimRight();
+
+               if(!str.IsEmpty())
+                       OpenPage(str, false);
+
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/TabBrowser/OpenDlg.h b/include/WTL/Samples/TabBrowser/OpenDlg.h
new file mode 100644 (file)
index 0000000..8374bc9
--- /dev/null
@@ -0,0 +1,66 @@
+// OpenDlg.h - COpenDlg class
+
+#pragma once
+
+
+class COpenDlg : public CDialogImpl<COpenDlg>
+{
+public:
+       enum { IDD = IDD_OPEN };
+
+       CString m_strURL;
+       bool m_bNewTab;
+
+       COpenDlg(LPCTSTR lpstrURL) : m_bNewTab(false)
+       {
+               m_strURL = lpstrURL;
+       }
+
+       BEGIN_MSG_MAP(COpenDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_ID_HANDLER(IDOK, OnOK)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+
+               if(m_strURL.IsEmpty())
+               {
+                       m_bNewTab = true;
+                       CButton btnCheck = GetDlgItem(IDC_NEW_TAB);
+                       btnCheck.SetCheck(1);
+                       btnCheck.EnableWindow(FALSE);
+               }
+               else
+               {
+                       CEdit edit = GetDlgItem(IDC_EDIT_URL);
+                       edit.SetWindowText(m_strURL);
+
+                       CButton btnCheck = GetDlgItem(IDC_NEW_TAB);
+                       btnCheck.SetCheck(m_bNewTab ? 1 : 0);
+               }
+
+               return TRUE;
+       }
+
+       LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               CEdit edit = GetDlgItem(IDC_EDIT_URL);
+               int nLen = edit.GetWindowTextLength();
+               edit.GetWindowText(m_strURL.GetBuffer(nLen), nLen + 1);
+               m_strURL.ReleaseBuffer();
+
+               CButton btnCheck = GetDlgItem(IDC_NEW_TAB);
+               m_bNewTab = (btnCheck.GetCheck() != 0);
+
+               EndDialog(wID);
+               return 0;
+       }
+
+       LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/TabBrowser/TabBrowser.cpp b/include/WTL/Samples/TabBrowser/TabBrowser.cpp
new file mode 100644 (file)
index 0000000..7b98d6d
--- /dev/null
@@ -0,0 +1,67 @@
+// TabBrowser.cpp : main source file for TabBrowser.exe
+//
+
+#include "stdafx.h"
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atlctrlx.h>
+#include <atlctrlw.h>
+#include <atldlgs.h>
+#include <atlmisc.h>
+
+#include "resource.h"
+
+#include "BrowserView.h"
+#include "CustomTabView.h"
+#include "AddressCombo.h"
+#include "OpenDlg.h"
+#include "WindowsDlg.h"
+#include "AboutDlg.h"
+#include "MainFrm.h"
+
+CAppModule _Module;
+
+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
+{
+       CMessageLoop theLoop;
+       _Module.AddMessageLoop(&theLoop);
+
+       CMainFrame wndMain;
+
+       if(wndMain.CreateEx() == NULL)
+       {
+               ATLTRACE(_T("Main window creation failed!\n"));
+               return 0;
+       }
+
+       wndMain.ShowWindow(nCmdShow);
+
+       int nRet = theLoop.Run();
+
+       _Module.RemoveMessageLoop();
+       return nRet;
+}
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+       HRESULT hRes = ::CoInitialize(NULL);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
+       ::DefWindowProc(NULL, 0, 0, 0L);
+
+       AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_USEREX_CLASSES);
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       AtlAxWinInit();
+
+       int nRet = Run(lpstrCmdLine, nCmdShow);
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/Samples/TabBrowser/TabBrowser.h b/include/WTL/Samples/TabBrowser/TabBrowser.h
new file mode 100644 (file)
index 0000000..1d9f8d1
--- /dev/null
@@ -0,0 +1 @@
+// TabBrowser.h
diff --git a/include/WTL/Samples/TabBrowser/TabBrowser70.sln b/include/WTL/Samples/TabBrowser/TabBrowser70.sln
new file mode 100644 (file)
index 0000000..7b91835
--- /dev/null
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabBrowser", "TabBrowser70.vcproj", "{4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}"
+EndProject
+Global
+       GlobalSection(SolutionConfiguration) = preSolution
+               ConfigName.0 = Debug
+               ConfigName.1 = Release
+       EndGlobalSection
+       GlobalSection(ProjectDependencies) = postSolution
+       EndGlobalSection
+       GlobalSection(ProjectConfiguration) = postSolution
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Debug.ActiveCfg = Debug|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Debug.Build.0 = Debug|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Release.ActiveCfg = Release|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Release.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+       EndGlobalSection
+       GlobalSection(ExtensibilityAddIns) = postSolution
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/TabBrowser/TabBrowser71.sln b/include/WTL/Samples/TabBrowser/TabBrowser71.sln
new file mode 100644 (file)
index 0000000..7ef2d99
--- /dev/null
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabBrowser", "TabBrowser71.vcproj", "{4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}"
+       ProjectSection(ProjectDependencies) = postProject
+       EndProjectSection
+EndProject
+Global
+       GlobalSection(SolutionConfiguration) = preSolution
+               Debug = Debug
+               Release = Release
+       EndGlobalSection
+       GlobalSection(ProjectConfiguration) = postSolution
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Debug.ActiveCfg = Debug|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Debug.Build.0 = Debug|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Release.ActiveCfg = Release|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Release.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+       EndGlobalSection
+       GlobalSection(ExtensibilityAddIns) = postSolution
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/TabBrowser/TabBrowser80.sln b/include/WTL/Samples/TabBrowser/TabBrowser80.sln
new file mode 100644 (file)
index 0000000..b796119
--- /dev/null
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabBrowser", "TabBrowser80.vcproj", "{4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Debug|Win32.ActiveCfg = Debug|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Debug|Win32.Build.0 = Debug|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Release|Win32.ActiveCfg = Release|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Release|Win32.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/TabBrowser/TabBrowser80x.sln b/include/WTL/Samples/TabBrowser/TabBrowser80x.sln
new file mode 100644 (file)
index 0000000..c6f8054
--- /dev/null
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabBrowser", "TabBrowser80x.vcproj", "{4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Debug|Win32.ActiveCfg = Debug|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Debug|Win32.Build.0 = Debug|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Release|Win32.ActiveCfg = Release|Win32
+               {4F93E0CE-7116-44A2-AEF1-9A6DE07C7CE0}.Release|Win32.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/TabBrowser/WindowsDlg.h b/include/WTL/Samples/TabBrowser/WindowsDlg.h
new file mode 100644 (file)
index 0000000..da5b9f4
--- /dev/null
@@ -0,0 +1,117 @@
+// WindowsDlg.h - CWindowsDlg class
+
+#pragma once
+
+
+class CWindowsDlg : public CDialogImpl<CWindowsDlg>, public CDialogResize<CWindowsDlg>
+{
+public:
+       enum { IDD = IDD_WINDOWS };
+
+       CCustomTabView* m_pTabView;
+       CListBox m_lb;
+
+       CWindowsDlg(CCustomTabView* pTabView) : m_pTabView(pTabView)
+       { }
+
+       void UpdateUI()
+       {
+               CButton btnActivate = GetDlgItem(IDC_ACTIVATE);
+               btnActivate.EnableWindow((m_lb.GetSelCount() == 1) ? TRUE : FALSE);
+
+               CButton btnClose = GetDlgItem(IDC_CLOSEWINDOWS);
+               btnClose.EnableWindow((m_lb.GetSelCount() != 0) ? TRUE : FALSE);
+       }
+
+       BEGIN_DLGRESIZE_MAP(CWindowsDlg)
+               DLGRESIZE_CONTROL(IDC_LIST1, DLSZ_SIZE_X | DLSZ_SIZE_Y)
+               DLGRESIZE_CONTROL(IDC_ACTIVATE, DLSZ_MOVE_X)
+               DLGRESIZE_CONTROL(IDC_CLOSEWINDOWS, DLSZ_MOVE_X)
+               DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X | DLSZ_MOVE_Y)
+       END_DLGRESIZE_MAP()
+
+       BEGIN_MSG_MAP(CWindowsDlg)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               COMMAND_HANDLER(IDC_LIST1, LBN_SELCHANGE, OnSelChange)
+               COMMAND_ID_HANDLER(IDC_ACTIVATE, OnActivate)
+               COMMAND_HANDLER(IDC_LIST1, LBN_DBLCLK, OnActivate)
+               COMMAND_ID_HANDLER(IDC_CLOSEWINDOWS, OnCloseWindows)
+               COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
+               COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+               CHAIN_MSG_MAP(CDialogResize<CWindowsDlg>)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+       {
+               CenterWindow(GetParent());
+
+               // Fill list box
+               m_lb = GetDlgItem(IDC_LIST1);
+               for(int i = 0; i < m_pTabView->GetPageCount(); i++)
+                       m_lb.AddString(m_pTabView->GetPageTitle(i));
+
+               m_lb.SetSel(m_pTabView->GetActivePage());
+
+               DlgResize_Init();
+
+               m_ptMinTrackSize.x /= 2;
+               m_ptMinTrackSize.y /= 2;
+
+               UpdateUI();
+
+               return TRUE;
+       }
+
+       LRESULT OnSelChange(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               UpdateUI();
+               return 0;
+       }
+
+       LRESULT OnActivate(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               int nSel = -1;
+               for(int i = 0; i < m_lb.GetCount(); i++)
+               {
+                       if(m_lb.GetSel(i) > 0)
+                       {
+                               nSel = i;
+                               break;
+                       }
+               }
+
+               if(nSel != -1)
+               {
+                       m_pTabView->SetActivePage(nSel);
+                       EndDialog(IDOK);
+               }
+
+               return 0;
+       }
+
+       LRESULT OnCloseWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               int nCount = m_lb.GetCount();
+               int nLast = -1;
+               for(int i = nCount - 1; i >= 0; i--)
+               {
+                       if(m_lb.GetSel(i) > 0)
+                       {
+                               m_pTabView->RemovePage(i);
+                               m_lb.DeleteString(i);
+                               nLast = i;
+                       }
+               }
+
+               if(nLast != -1)
+                       m_lb.SetSel(nLast);
+
+               return 0;
+       }
+
+       LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+       {
+               EndDialog(wID);
+               return 0;
+       }
+};
diff --git a/include/WTL/Samples/TabBrowser/res/Go.bmp b/include/WTL/Samples/TabBrowser/res/Go.bmp
new file mode 100644 (file)
index 0000000..b9dae44
Binary files /dev/null and b/include/WTL/Samples/TabBrowser/res/Go.bmp differ
diff --git a/include/WTL/Samples/TabBrowser/res/PageImage.bmp b/include/WTL/Samples/TabBrowser/res/PageImage.bmp
new file mode 100644 (file)
index 0000000..c3a5ca6
Binary files /dev/null and b/include/WTL/Samples/TabBrowser/res/PageImage.bmp differ
diff --git a/include/WTL/Samples/TabBrowser/res/TabBrowser.ico b/include/WTL/Samples/TabBrowser/res/TabBrowser.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/Samples/TabBrowser/res/TabBrowser.ico differ
diff --git a/include/WTL/Samples/TabBrowser/res/TabToolbar.bmp b/include/WTL/Samples/TabBrowser/res/TabToolbar.bmp
new file mode 100644 (file)
index 0000000..b4cc117
Binary files /dev/null and b/include/WTL/Samples/TabBrowser/res/TabToolbar.bmp differ
diff --git a/include/WTL/Samples/TabBrowser/res/Toolbar.bmp b/include/WTL/Samples/TabBrowser/res/Toolbar.bmp
new file mode 100644 (file)
index 0000000..d699077
Binary files /dev/null and b/include/WTL/Samples/TabBrowser/res/Toolbar.bmp differ
diff --git a/include/WTL/Samples/TabBrowser/res/Toolbar_Big.bmp b/include/WTL/Samples/TabBrowser/res/Toolbar_Big.bmp
new file mode 100644 (file)
index 0000000..cd4d19c
Binary files /dev/null and b/include/WTL/Samples/TabBrowser/res/Toolbar_Big.bmp differ
diff --git a/include/WTL/Samples/TabBrowser/resource.h b/include/WTL/Samples/TabBrowser/resource.h
new file mode 100644 (file)
index 0000000..9cb48de
--- /dev/null
@@ -0,0 +1,63 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by TabBrowser.RC
+//
+
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDS_OPEN_ERROR                  129
+#define IDD_OPEN                        201
+#define IDD_WINDOWS                     202
+#define IDR_TABTOOLBAR                  203
+#define IDB_PAGEIMAGE                   204
+#define IDR_MAINFRAME_BIG               205
+#define IDR_GO                          207
+#define IDR_TOOLBAR_MENU                210
+#define IDC_EDIT_URL                    1000
+#define IDC_LIST1                       1001
+#define IDC_ACTIVATE                    1002
+#define IDC_CLOSEWINDOWS                1003
+#define IDC_NEW_TAB                     1004
+#define ID_LINKS_FIRST                  31000
+#define ID_LINKS_MICROSOFT              31000
+#define ID_LINKS_MSDN                   31001
+#define ID_LINKS_LIVE                   31002
+#define ID_LINKS_UPDATE                 31003
+#define ID_LINKS_WTL                    31004
+#define ID_LINKS_LAST                   31099
+#define ID_LINKS_URL_FIRST              31100
+#define ID_LINKS_URL_MICROSOFT          31100
+#define ID_LINKS_URL_MSDN               31101
+#define ID_LINKS_URL_LIVE               31102
+#define ID_LINKS_URL_UPDATE             31103
+#define ID_LINKS_URL_WTL                31104
+#define ID_LINKS_URL_LAST               31199
+#define ID_WINDOW_CLOSE                 32773
+#define ID_WINDOW_CLOSE_ALL             32776
+#define ID_BROWSER_BACK                 32777
+#define ID_BROWSER_FORWARD              32778
+#define ID_BROWSER_REFRESH              32779
+#define ID_BROWSER_STOP                 32782
+#define ID_WINDOW_SHOW_VIEWS            32783
+#define ID_BROWSER_HOME                 32791
+#define ID_BROWSER_SEARCH               32795
+#define ID_VIEW_ADDRESS_BAR             32796
+#define ID_GO                           32797
+#define IDS_LOADING                     32798
+#define IDS_ADDRESS                     32799
+#define IDS_LINKS                       32800
+#define IDS_BLANK_URL                   32801
+#define IDS_BLANK_TITLE                 32802
+#define ID_VIEW_LOCK_TOOLBARS           32807
+#define ID_VIEW_LINKS_BAR               32808
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        211
+#define _APS_NEXT_COMMAND_VALUE         32810
+#define _APS_NEXT_CONTROL_VALUE         1005
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/TabBrowser/stdafx.cpp b/include/WTL/Samples/TabBrowser/stdafx.cpp
new file mode 100644 (file)
index 0000000..5b8256b
--- /dev/null
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     TabBrowser.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
diff --git a/include/WTL/Samples/TabBrowser/stdafx.h b/include/WTL/Samples/TabBrowser/stdafx.h
new file mode 100644 (file)
index 0000000..f702318
--- /dev/null
@@ -0,0 +1,73 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#pragma once
+
+// Change these values to use different versions
+#define WINVER         0x0500
+#define _WIN32_WINNT   0x0501
+#define _WIN32_IE      0x0501
+#define _RICHEDIT_VER  0x0100
+
+#define _WTL_USE_CSTRING
+
+#ifdef _VC80X
+  // Support for VS2005 Express & SDK ATL
+  #define _CRT_SECURE_NO_DEPRECATE
+  #pragma conform(forScope, off)
+  #pragma comment(linker, "/NODEFAULTLIB:atlthunk.lib")
+  #pragma warning(disable: 4565) // redefinition; the symbol was previously declared with __declspec(noalias)
+  #pragma warning(disable: 4068) // unknown pragma
+#endif // _VC80X
+
+#include <atlbase.h>
+
+#ifdef _VC80X
+  // Support for VS2005 Express & SDK ATL
+  namespace ATL
+  {
+       inline void * __stdcall __AllocStdCallThunk()
+       {
+               return ::HeapAlloc(::GetProcessHeap(), 0, sizeof(_stdcallthunk));
+       }
+
+       inline void __stdcall __FreeStdCallThunk(void *p)
+       {
+               ::HeapFree(::GetProcessHeap(), 0, p);
+       }
+  };
+#endif // _VC80X
+
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#if (_ATL_VER < 0x0700)
+  #pragma warning(disable: 4100) // unreferenced formal parameter
+  #pragma warning(disable: 4189) // local variable is initialized but not referenced
+#endif
+
+#include <atlcom.h>
+
+#if (_ATL_VER < 0x0700)
+  #pragma warning(default: 4100)
+  #pragma warning(default: 4189)
+#endif
+
+#include <atlhost.h>
+#include <atlwin.h>
+#include <atlctl.h>
+
+#ifdef _EMBEDDED_MANIFEST
+  #if defined _M_IX86
+    #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+  #elif defined _M_IA64
+    #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+  #elif defined _M_X64
+    #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+  #else
+    #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+  #endif
+#endif // _EMBEDDED_MANIFEST
diff --git a/include/WTL/Samples/WTLExplorer/ExplorerCombo.H b/include/WTL/Samples/WTLExplorer/ExplorerCombo.H
new file mode 100644 (file)
index 0000000..93d9a15
--- /dev/null
@@ -0,0 +1,104 @@
+// explorercombo.h
+
+#ifndef __EXPLORERCOMBO_H__
+#define __EXPLORERCOMBO_H__
+
+#pragma once
+
+#include "resource.h"
+
+
+class CExplorerCombo : public CWindowImpl<CExplorerCombo, CComboBoxEx>
+{
+public:
+       enum
+       {
+               m_cxGap = 2,
+               m_cxMinDropWidth = 200
+       };
+
+       CComboBox m_cb;
+       CToolBarCtrl m_tb;
+       SIZE m_sizeTB;
+
+       DECLARE_WND_SUPERCLASS(_T("WtlExplorer_ComboBox"), CComboBoxEx::GetWndClassName())
+
+       BEGIN_MSG_MAP(CExplorerCombo)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
+               MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
+       {
+               // let the combo box initialize itself
+               LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
+
+               if(lRet != -1)
+               {
+                       // adjust the drop-down width
+                       m_cb = GetComboCtrl();
+                       m_cb.SetDroppedWidth(m_cxMinDropWidth);
+
+                       // create a toolbar for the GO button
+                       m_tb = CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(m_hWnd, IDT_GO1, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST);
+                       LPCTSTR lpszStrings = _T("Go\0");
+                       m_tb.AddStrings(lpszStrings);
+
+                       RECT rect;
+                       m_tb.GetItemRect(0, &rect);
+                       m_sizeTB.cx = rect.right;
+                       m_sizeTB.cy = rect.bottom;
+               }
+
+               return lRet;
+       }
+
+       LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
+       {
+               CDCHandle dc = (HDC)wParam;
+               CWindow wndParent = GetParent();
+
+               // Forward this to the parent window, rebar bands are transparent
+               POINT pt = { 0, 0 };
+               MapWindowPoints(wndParent, &pt, 1);
+               dc.OffsetWindowOrg(pt.x, pt.y, &pt);
+               LRESULT lRet = wndParent.SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
+               dc.SetWindowOrg(pt.x, pt.y);
+
+               bHandled = (lRet != 0);
+               return lRet;
+       }
+
+       LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+       {
+               if(m_tb.m_hWnd == NULL)
+               {
+                       bHandled = FALSE;
+                       return 1;
+               }
+
+               // copy the WINDOWPOS struct and adjust for the GO button
+               WINDOWPOS wp = *(LPWINDOWPOS)lParam;
+               wp.cx -= m_sizeTB.cx + m_cxGap;
+               LRESULT lRet = DefWindowProc(uMsg, wParam, (LPARAM)&wp);
+
+               // paint below the GO button
+               RECT rcGo = { wp.cx, 0, wp.cx + m_sizeTB.cx + m_cxGap, wp.cy };
+               InvalidateRect(&rcGo);
+
+               // center the GO button relative to the combo box
+               RECT rcCombo;
+               m_cb.GetWindowRect(&rcCombo);
+               int y = (rcCombo.bottom - rcCombo.top - m_sizeTB.cy) / 2;
+//             if(y < 0)
+//                     y = 0;
+
+               // position the GO button on the right
+               m_tb.SetWindowPos(NULL, wp.cx + m_cxGap, y, m_sizeTB.cx, m_sizeTB.cy, SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
+
+               return lRet;
+       }
+};
+
+#endif //__EXPLORERCOMBO_H__
diff --git a/include/WTL/Samples/WTLExplorer/MainFrm.Cpp b/include/WTL/Samples/WTLExplorer/MainFrm.Cpp
new file mode 100644 (file)
index 0000000..d05fe12
--- /dev/null
@@ -0,0 +1,718 @@
+// mainframe.cpp
+
+#include "stdafx.h"
+
+#include <shlobj.h>
+#include <shlguid.h>
+#include <ntquery.h>
+
+#include "mainfrm.h"
+
+
+BOOL CMainFrame::FillListView(LPTVITEMDATA lptvid, LPSHELLFOLDER pShellFolder)
+{
+       ATLASSERT(pShellFolder != NULL);
+
+       CComPtr<IEnumIDList> spEnumIDList;
+       HRESULT hr = pShellFolder->EnumObjects(m_wndListView.GetParent(), SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &spEnumIDList);
+       if (FAILED(hr))
+               return FALSE;
+
+       CShellItemIDList lpifqThisItem;
+       CShellItemIDList lpi;
+       ULONG ulFetched = 0;
+       UINT uFlags = 0;
+       LVITEM lvi = { 0 };
+       lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
+       int iCtr = 0;
+
+       while (spEnumIDList->Next(1, &lpi, &ulFetched) == S_OK)
+       {
+               // Get some memory for the ITEMDATA structure.
+               LPLVITEMDATA lplvid = new LVITEMDATA;
+               if (lplvid == NULL) 
+                       return FALSE;
+
+               // Since you are interested in the display attributes as well as other attributes, 
+               // you need to set ulAttrs to SFGAO_DISPLAYATTRMASK before calling GetAttributesOf()
+               ULONG ulAttrs = SFGAO_DISPLAYATTRMASK;
+               hr = pShellFolder->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);
+               if(FAILED(hr)) 
+                       return FALSE;
+
+               lplvid->ulAttribs = ulAttrs;
+
+               lpifqThisItem = m_ShellMgr.ConcatPidls(lptvid->lpifq, lpi);
+
+               lvi.iItem = iCtr;
+               lvi.iSubItem = 0;
+               lvi.pszText = LPSTR_TEXTCALLBACK;
+               lvi.cchTextMax = MAX_PATH;
+               uFlags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;
+               lvi.iImage = I_IMAGECALLBACK;
+
+               lplvid->spParentFolder.p = pShellFolder;
+               pShellFolder->AddRef();
+
+               // Now make a copy of the ITEMIDLIST
+               lplvid->lpi= m_ShellMgr.CopyITEMID(lpi);
+
+               lvi.lParam = (LPARAM)lplvid;
+
+               // Add the item to the list view control
+               int n = m_wndListView.InsertItem(&lvi);
+               m_wndListView.AddItem(n, 1, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK);
+               m_wndListView.AddItem(n, 2, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK);
+               m_wndListView.AddItem(n, 3, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK);
+               m_wndListView.AddItem(n, 4, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK);
+
+               iCtr++;
+               lpifqThisItem = NULL;
+               lpi = NULL;   // free PIDL the shell gave you
+       }
+
+       SortData sd(m_nSort, m_bReverseSort);
+       m_wndListView.SortItems(CMainFrame::ListViewCompareProc, (LPARAM)&sd);
+
+       return TRUE;
+}
+
+int CALLBACK CMainFrame::ListViewCompareProc(LPARAM lparam1, LPARAM lparam2, LPARAM lParamSort)
+{
+       ATLASSERT(lParamSort != NULL);
+
+       LPLVITEMDATA lplvid1 = (LPLVITEMDATA)lparam1;
+       LPLVITEMDATA lplvid2 = (LPLVITEMDATA)lparam2;
+       SortData* pSD = (SortData*)lParamSort;
+
+       HRESULT hr = 0;
+       if(pSD->bReverseSort)
+               hr = lplvid1->spParentFolder->CompareIDs(0, lplvid2->lpi, lplvid1->lpi);
+       else
+               hr = lplvid1->spParentFolder->CompareIDs(0, lplvid1->lpi, lplvid2->lpi);
+
+       return (int)(short)HRESULT_CODE(hr);
+}
+
+HRESULT CMainFrame::FillTreeView(IShellFolder* pShellFolder, LPITEMIDLIST lpifq, HTREEITEM hParent)
+{
+       if(pShellFolder == NULL)
+               return E_POINTER;
+
+       CComPtr<IEnumIDList> spIDList;
+       HRESULT hr = pShellFolder->EnumObjects(m_hWnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &spIDList);
+       if (FAILED(hr))
+               return hr;
+
+       CShellItemIDList lpi;
+       CShellItemIDList lpifqThisItem;
+       LPTVITEMDATA lptvid = NULL;
+       ULONG ulFetched = 0;
+
+       TCHAR szBuff[256] = { 0 };
+
+       TVITEM tvi = { 0 };             // TreeView Item
+       TVINSERTSTRUCT tvins = { 0 };   // TreeView Insert Struct
+       HTREEITEM hPrev = NULL;         // Previous Item Added
+       COMBOBOXEXITEM cbei = { 0 };
+
+       // Hourglass on
+       CWaitCursor wait;
+
+       int iCnt = 0;
+       while (spIDList->Next(1, &lpi, &ulFetched) == S_OK)
+       {
+               // Create a fully qualified path to the current item
+               // The SH* shell api's take a fully qualified path pidl,
+               // (see GetIcon above where I call SHGetFileInfo) whereas the
+               // interface methods take a relative path pidl.
+               ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;
+               pShellFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&lpi, &ulAttrs);
+               if ((ulAttrs & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER)) != 0)
+               {
+                       // We need this next if statement so that we don't add things like
+                       // the MSN to our tree. MSN is not a folder, but according to the
+                       // shell is has subfolders....
+                       if (ulAttrs & SFGAO_FOLDER)
+                       {
+                               tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
+                               cbei.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
+
+                               if (ulAttrs & SFGAO_HASSUBFOLDER)
+                               {
+                                       // This item has sub-folders, so let's put the + in the TreeView.
+                                       // The first time the user clicks on the item, we'll populate the
+                                       // sub-folders then.
+                                       tvi.cChildren = 1;
+                                       tvi.mask |= TVIF_CHILDREN;
+                               }
+
+                               // OK, let's get some memory for our ITEMDATA struct
+                               lptvid = new TVITEMDATA;
+                               if (lptvid == NULL)
+                                       return E_FAIL;
+
+                               // Now get the friendly name that we'll put in the treeview...
+                               if (!m_ShellMgr.GetName(pShellFolder, lpi, SHGDN_NORMAL, szBuff))
+                                       return E_FAIL;
+
+                               tvi.pszText = szBuff;
+                               tvi.cchTextMax = MAX_PATH;
+
+                               cbei.pszText = szBuff;
+                               cbei.cchTextMax = MAX_PATH;
+
+                               lpifqThisItem = m_ShellMgr.ConcatPidls(lpifq, lpi);
+
+                               // Now, make a copy of the ITEMIDLIST
+                               lptvid->lpi=m_ShellMgr.CopyITEMID(lpi);
+
+                               m_ShellMgr.GetNormalAndSelectedIcons(lpifqThisItem, &tvi);
+
+                               lptvid->spParentFolder.p = pShellFolder;    // Store the parent folders SF
+                               pShellFolder->AddRef();
+
+                               lptvid->lpifq = m_ShellMgr.ConcatPidls(lpifq, lpi);
+
+                               tvi.lParam = (LPARAM)lptvid;
+
+                               tvins.item = tvi;
+                               tvins.hInsertAfter = hPrev;
+                               tvins.hParent = hParent;
+
+                               // Add the item to the tree and combo
+                               hPrev = TreeView_InsertItem(m_wndTreeView.m_hWnd, &tvins);
+                               cbei.iItem = iCnt++;    
+                               cbei.iImage = tvi.iImage;
+                               cbei.iSelectedImage = tvi.iSelectedImage;
+
+                               int nIndent = 0;
+                               while(NULL != (hPrev = (HTREEITEM)m_wndTreeView.SendMessage(TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hPrev)))
+                               {
+                                       nIndent++;
+                               }
+
+                               cbei.iIndent = nIndent;
+                               m_wndCombo.SendMessage(CBEM_INSERTITEM, 0, (LPARAM)&cbei);
+                       }
+
+                       lpifqThisItem = NULL;
+               }
+
+               lpi = NULL;   // Finally, free the pidl that the shell gave us...
+       }
+
+       return hr;
+}
+
+int CALLBACK CMainFrame::TreeViewCompareProc(LPARAM lparam1, LPARAM lparam2, LPARAM /*lparamSort*/)
+{
+       LPTVITEMDATA lptvid1 = (LPTVITEMDATA)lparam1;
+       LPTVITEMDATA lptvid2 = (LPTVITEMDATA)lparam2;
+
+       HRESULT hr = lptvid1->spParentFolder->CompareIDs(0, lptvid1->lpi, lptvid2->lpi);
+
+       return (int)(short)HRESULT_CODE(hr);
+}
+
+HWND CMainFrame::CreateAddressBarCtrl(HWND hWndParent)
+{
+       RECT rc = { 50, 0, 300, 100 };
+       m_wndCombo.Create(hWndParent, rc, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBS_DROPDOWN | CBS_AUTOHSCROLL);
+       m_wndCombo.SetFont(AtlGetDefaultGuiFont());
+
+       return m_wndCombo;
+}
+
+LRESULT CMainFrame::OnCreate(UINT, WPARAM, LPARAM, BOOL&)
+{
+       
+       // create command bar window
+       RECT rcCmdBar = { 0, 0, 100, 100 };
+       HWND hWndCmdBar = m_wndCmdBar.Create(m_hWnd, rcCmdBar, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
+       // atach menu
+       m_wndCmdBar.AttachMenu(GetMenu());
+       // load command bar images
+       m_wndCmdBar.LoadImages(IDR_MAINFRAME);
+       // remove old menu
+       SetMenu(NULL);
+
+       HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
+       HWND hWndAddressBar = CreateAddressBarCtrl(m_hWnd);
+
+       CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
+
+       AddSimpleReBarBand(hWndCmdBar);
+       AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
+       AddSimpleReBarBand(hWndAddressBar, _T("Address"), TRUE);
+
+       CreateSimpleStatusBar();
+
+       m_hWndClient = m_wndSplitter.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+
+       m_wndFolderTree.Create(m_wndSplitter, _T("Folders"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+       
+       m_wndTreeView.Create(m_wndFolderTree, rcDefault, NULL, 
+               WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 
+               TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, 
+               WS_EX_CLIENTEDGE);
+
+       m_wndFolderTree.SetClient(m_wndTreeView);
+
+       m_wndListView.Create(m_wndSplitter, rcDefault, NULL, 
+               WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 
+               LVS_REPORT | LVS_AUTOARRANGE | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS,
+               WS_EX_CLIENTEDGE);
+       m_wndListView.SetExtendedListViewStyle(LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_UNDERLINEHOT);
+       
+       InitViews();
+
+       UpdateLayout();
+
+       m_wndSplitter.SetSplitterPanes(m_wndFolderTree, m_wndListView);
+
+       RECT rect;
+       GetClientRect(&rect);
+       m_wndSplitter.SetSplitterPos((rect.right - rect.left) / 4);
+
+       UIAddToolBar(hWndToolBar);
+       UISetCheck(ID_VIEW_TOOLBAR, 1);
+       UISetCheck(ID_VIEW_ADDRESS_BAR, 1);
+       UISetCheck(ID_VIEW_STATUS_BAR, 1);
+       UISetCheck(ID_VIEW_DETAILS, 1);
+       UISetCheck(ID_VIEW_SORT_NAME, 1);
+
+       CMessageLoop* pLoop = _Module.GetMessageLoop();
+       pLoop->AddMessageFilter(this);
+       pLoop->AddIdleHandler(this);
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnViewChange(WORD, WORD wID, HWND, BOOL&)
+{
+       UISetCheck(ID_VIEW_ICONS, FALSE);
+       UISetCheck(ID_VIEW_SMALL_ICONS, FALSE);
+       UISetCheck(ID_VIEW_LIST, FALSE);
+       UISetCheck(ID_VIEW_DETAILS, FALSE);
+       UISetCheck(wID, TRUE);
+       DWORD dwNewStyle = (int)wID - ID_VIEW_ICONS;
+       m_wndListView.SetViewType(dwNewStyle);
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnComboGo(WORD, WORD, HWND, BOOL&)
+{
+//     TCHAR szBuff[MAX_PATH] = { 0 };
+//     m_wndCombo.GetWindowText(szBuff, MAX_PATH);
+//             
+//     m_wndTreeView.SelectItem(NULL);
+       //m_wndCombo.SetEditSel(0, -1);
+       //FillListView(m_wndListView, szBuff);
+
+       MessageBox(_T("Not yet implemented!"), _T("WTL Explorer"), MB_OK | MB_ICONINFORMATION);
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnViewRefresh(WORD, WORD, HWND, BOOL&)
+{
+       MessageBox(_T("Not yet implemented!"), _T("WTL Explorer"), MB_OK | MB_ICONINFORMATION);
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnViewSort(WORD, WORD wID, HWND, BOOL&)
+{
+       UISetCheck(ID_VIEW_SORT_NAME, FALSE);
+       UISetCheck(ID_VIEW_SORT_SIZE, FALSE);
+       UISetCheck(ID_VIEW_SORT_TYPE, FALSE);
+       UISetCheck(ID_VIEW_SORT_TIME, FALSE);
+       UISetCheck(ID_VIEW_SORT_ATTR, FALSE);
+       UISetCheck(wID, TRUE);
+       m_bReverseSort = false;
+       m_nSort = (int)wID - ID_VIEW_SORT_NAME;
+       ATLASSERT(m_nSort >= 0 && m_nSort <= 4);
+       SortData sd(m_nSort, m_bReverseSort);
+       m_wndListView.SortItems(CMainFrame::ListViewCompareProc, (LPARAM)&sd);
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnTVSelChanged(int, LPNMHDR pnmh, BOOL&)
+{
+       LPNMTREEVIEW lpTV = (LPNMTREEVIEW)pnmh;
+       LPTVITEMDATA lptvid = (LPTVITEMDATA)lpTV->itemNew.lParam;
+       if (lptvid != NULL)
+       {
+               CComPtr<IShellFolder> spFolder;
+               HRESULT hr=lptvid->spParentFolder->BindToObject(lptvid->lpi, 0, IID_IShellFolder, (LPVOID *)&spFolder);
+               if(FAILED(hr))
+                       return hr;
+               
+               if(m_wndListView.GetItemCount() > 0)
+                       m_wndListView.DeleteAllItems();
+               FillListView(lptvid, spFolder);
+               
+               TCHAR psz[MAX_PATH] = { 0 };
+               m_ShellMgr.GetName(lptvid->spParentFolder, lptvid->lpi, SHGDN_FORPARSING, psz);
+               
+               if(StrChr(psz, _T('{')))   //special case
+                       m_ShellMgr.GetName(lptvid->spParentFolder, lptvid->lpi, SHGDN_NORMAL, psz);
+       
+               int nImage = 0;
+               int nSelectedImage = 0;
+               m_wndTreeView.GetItemImage(lpTV->itemNew.hItem, nImage, nSelectedImage);
+               COMBOBOXEXITEM cbei;
+               cbei.mask = CBEIF_TEXT | CBEIF_INDENT |CBEIF_IMAGE| CBEIF_SELECTEDIMAGE;
+               cbei.iItem = -1; //Editbox of the comboboxex
+               cbei.pszText =psz;
+               cbei.cchTextMax = MAX_PATH;
+               if(m_wndTreeView.ItemHasChildren(lpTV->itemNew.hItem))
+               {
+                       cbei.iImage = nImage;
+                       cbei.iSelectedImage = nImage;
+               }
+               else 
+               {
+                       cbei.iImage = nSelectedImage;
+                       cbei.iSelectedImage = nSelectedImage;
+               }
+               cbei.iIndent = 1;
+               
+               m_wndCombo.SetItem(&cbei);
+               
+       }
+
+       return 0L;
+}
+
+LRESULT CMainFrame::OnTVItemExpanding(int, LPNMHDR pnmh, BOOL&)
+{
+       CWaitCursor wait;
+       LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)pnmh;
+       if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE))
+                return 0L;
+
+       LPTVITEMDATA lptvid=(LPTVITEMDATA)pnmtv->itemNew.lParam;
+       
+       CComPtr<IShellFolder> spFolder;
+       HRESULT hr=lptvid->spParentFolder->BindToObject(lptvid->lpi, 0, IID_IShellFolder, (LPVOID *)&spFolder);
+       if(FAILED(hr))
+               return hr;
+       
+       FillTreeView(spFolder, lptvid->lpifq, pnmtv->itemNew.hItem);
+       
+       TVSORTCB tvscb;
+       tvscb.hParent = pnmtv->itemNew.hItem;
+       tvscb.lpfnCompare = CMainFrame::TreeViewCompareProc;
+       tvscb.lParam = 0;
+
+       TreeView_SortChildrenCB(m_wndTreeView.m_hWnd, &tvscb, 0);
+       
+       return 0L;
+
+}
+
+LRESULT CMainFrame::OnTVDeleteItem(int, LPNMHDR pnmh, BOOL&)
+{
+       LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)pnmh;
+       LPTVITEMDATA lptvid = (LPTVITEMDATA)pnmtv->itemOld.lParam;
+       delete lptvid;
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnLVGetDispInfo(int, LPNMHDR pnmh, BOOL&)
+{
+       NMLVDISPINFO* plvdi = (NMLVDISPINFO*)pnmh;
+       if(plvdi == NULL)
+               return 0L;
+
+       LPLVITEMDATA lplvid = (LPLVITEMDATA)plvdi->item.lParam;
+
+       HTREEITEM hti = m_wndTreeView.GetSelectedItem();
+       TVITEM tvi = { 0 };
+       tvi.mask = TVIF_PARAM;
+       tvi.hItem = hti;
+
+       m_wndTreeView.GetItem(&tvi);
+       if(tvi.lParam <= 0)
+               return 0L;
+
+       LPTVITEMDATA lptvid = (LPTVITEMDATA)tvi.lParam;
+       if (lptvid == NULL)
+               return 0L;
+       
+       CShellItemIDList pidlTemp = m_ShellMgr.ConcatPidls(lptvid->lpifq, lplvid->lpi);
+       plvdi->item.iImage = m_ShellMgr.GetIconIndex(pidlTemp, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
+       if (plvdi->item.iSubItem == 0 && (plvdi->item.mask & LVIF_TEXT) )   // File Name
+       {
+               m_ShellMgr.GetName(lplvid->spParentFolder, lplvid->lpi, SHGDN_NORMAL, plvdi->item.pszText);
+       }       
+       else
+       {
+               CComPtr<IShellFolder2> spFolder2;
+               HRESULT hr = lptvid->spParentFolder->QueryInterface(IID_IShellFolder2, (void**)&spFolder2);
+               if(FAILED(hr))
+                       return hr;
+
+               SHELLDETAILS sd = { 0 };
+               sd.fmt = LVCFMT_CENTER;
+               sd.cxChar = 15;
+               
+               hr = spFolder2->GetDetailsOf(lplvid->lpi, plvdi->item.iSubItem, &sd);
+               if(FAILED(hr))
+                       return hr;
+
+               if(sd.str.uType == STRRET_WSTR)
+               {
+                       StrRetToBuf(&sd.str, lplvid->lpi.m_pidl, m_szListViewBuffer, MAX_PATH);
+                       plvdi->item.pszText=m_szListViewBuffer;
+               }
+               else if(sd.str.uType == STRRET_OFFSET)
+               {
+                       plvdi->item.pszText = (LPTSTR)lptvid->lpi + sd.str.uOffset;
+               }
+               else if(sd.str.uType == STRRET_CSTR)
+               {
+                       USES_CONVERSION;
+                       plvdi->item.pszText = A2T(sd.str.cStr);
+               }
+       }
+       
+       plvdi->item.mask |= LVIF_DI_SETITEM;
+
+       return 0L;
+}
+
+LRESULT CMainFrame::OnLVColumnClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+{
+       LPNMLISTVIEW lpLV = (LPNMLISTVIEW)pnmh;
+       if(m_nSort == lpLV->iSubItem)
+               m_bReverseSort = !m_bReverseSort;
+       else
+               m_nSort = lpLV->iSubItem;
+       ATLASSERT(m_nSort >= 0 && m_nSort <= 4);
+       SortData sd(m_nSort, m_bReverseSort);
+       m_wndListView.SortItems(CMainFrame::ListViewCompareProc, (LPARAM)&sd);
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnNMRClick(int, LPNMHDR pnmh, BOOL&)
+{
+       POINT pt = { 0, 0 };
+       ::GetCursorPos(&pt);
+       POINT ptClient = pt;
+       if(pnmh->hwndFrom != NULL)
+               ::ScreenToClient(pnmh->hwndFrom, &ptClient);
+       
+       if(pnmh->hwndFrom == m_wndTreeView.m_hWnd)
+       {
+               TVHITTESTINFO tvhti = { 0 };
+               tvhti.pt = ptClient;
+               m_wndTreeView.HitTest(&tvhti);
+               if ((tvhti.flags & TVHT_ONITEMLABEL) != 0)
+               {
+                       TVITEM tvi = { 0 };
+                       tvi.mask = TVIF_PARAM;
+                       tvi.hItem = tvhti.hItem;
+                       if (m_wndTreeView.GetItem(&tvi) != FALSE)
+                       {
+                               LPTVITEMDATA lptvid = (LPTVITEMDATA)tvi.lParam;
+                               if (lptvid != NULL)
+                                       m_ShellMgr.DoContextMenu(::GetParent(m_wndTreeView.m_hWnd), lptvid->spParentFolder, lptvid->lpi, pt);
+                       }
+               }
+       }
+       else if(pnmh->hwndFrom == m_wndListView.m_hWnd)
+       {
+               LVHITTESTINFO lvhti = { 0 };
+               lvhti.pt = ptClient;
+               m_wndListView.HitTest(&lvhti);
+               if ((lvhti.flags & LVHT_ONITEMLABEL) != 0)
+               {
+                       LVITEM lvi = { 0 };
+                       lvi.mask = LVIF_PARAM;
+                       lvi.iItem = lvhti.iItem;
+                       if (m_wndListView.GetItem(&lvi) != FALSE)
+                       {
+                               LPLVITEMDATA lptvid = (LPLVITEMDATA)lvi.lParam;
+                               if (lptvid != NULL)
+                                       m_ShellMgr.DoContextMenu(::GetParent(m_wndListView.m_hWnd), lptvid->spParentFolder, lptvid->lpi, pt);
+                       }
+               }
+       }
+
+       return 0L;
+}
+
+LRESULT CMainFrame::OnLVItemClick(int, LPNMHDR pnmh, BOOL&)
+{
+
+       if(pnmh->hwndFrom != m_wndListView.m_hWnd)
+               return 0L;
+       POINT pt;
+       ::GetCursorPos((LPPOINT)&pt);
+       m_wndListView.ScreenToClient(&pt);
+
+       LVHITTESTINFO lvhti;
+       lvhti.pt = pt;
+       m_wndListView.HitTest(&lvhti);
+       LVITEM lvi;
+
+       if (lvhti.flags & LVHT_ONITEM)
+       {
+               m_wndListView.ClientToScreen(&pt);
+               lvi.mask = LVIF_PARAM;
+               lvi.iItem = lvhti.iItem;
+               lvi.iSubItem = 0;
+
+               if (!m_wndListView.GetItem(&lvi))
+                       return 0;
+
+               LPLVITEMDATA lplvid=(LPLVITEMDATA)lvi.lParam;
+
+               if(lplvid == NULL)
+               {
+                       return 0L;
+               }
+               else if ((lplvid->ulAttribs & SFGAO_FOLDER) == 0)
+               {
+                       SHELLEXECUTEINFO sei =
+                       {
+                               sizeof(SHELLEXECUTEINFO),
+                               SEE_MASK_INVOKEIDLIST,               // fMask
+                               ::GetParent(m_wndListView.m_hWnd),   // hwnd of parent
+                               _T("Open"),                          // lpVerb
+                               NULL,                                // lpFile
+                               _T(""),
+                               _T(""),                              // lpDirectory
+                               SW_SHOWNORMAL,                       // nShow
+                               _Module.GetModuleInstance(),         // hInstApp
+                               (LPVOID)NULL,                        // lpIDList...will set below
+                               NULL,                                // lpClass
+                               0,                                   // hkeyClass
+                               0,                                   // dwHotKey
+                               NULL                                 // hIcon
+                       };
+                       sei.lpIDList = m_ShellMgr.GetFullyQualPidl(lplvid->spParentFolder, lplvid->lpi);
+                       ::ShellExecuteEx(&sei);
+               }
+               else
+               {
+                       MessageBox(_T("Clicked on folder"));
+               }
+       }
+
+       return 0L;
+}
+
+LRESULT CMainFrame::OnLVDeleteItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
+{
+       LPNMLISTVIEW pnmlv = (LPNMLISTVIEW)pnmh;
+
+       LVITEM lvi;
+       lvi.mask = LVIF_PARAM;
+       lvi.iItem = pnmlv->iItem;
+       lvi.iSubItem = 0;
+
+       if (!m_wndListView.GetItem(&lvi))
+               return 0;
+
+       LPLVITEMDATA lplvid = (LPLVITEMDATA)lvi.lParam;
+       delete lplvid;
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       PostMessage(WM_CLOSE);
+       return 0;
+}
+
+LRESULT CMainFrame::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       // TODO: add code to initialize document
+
+       return 0;
+}
+
+LRESULT CMainFrame::OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
+       return 0;
+}
+
+LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       static BOOL bNew = TRUE;        // initially visible
+       bNew = !bNew;
+       ::SendMessage(m_hWndToolBar, RB_SHOWBAND, 1, bNew);     // toolbar is band #1
+       UISetCheck(ID_VIEW_TOOLBAR, bNew);
+       UpdateLayout();
+       return 0;
+}
+
+LRESULT CMainFrame::OnViewAddressBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       static BOOL bNew = TRUE;        // initially visible
+       bNew = !bNew;
+       ::SendMessage(m_hWndToolBar, RB_SHOWBAND, 2, bNew);     // address bar is band #2
+       UISetCheck(ID_VIEW_ADDRESS_BAR, bNew);
+       UpdateLayout();
+       return 0;
+}
+
+LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       BOOL bNew = !::IsWindowVisible(m_hWndStatusBar);
+       ::ShowWindow(m_hWndStatusBar, bNew ? SW_SHOWNOACTIVATE : SW_HIDE);
+       UISetCheck(ID_VIEW_STATUS_BAR, bNew);
+       UpdateLayout();
+       return 0;
+}
+
+LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       ::ShellAbout(m_hWnd, _T("WTL Explorer"), _T("This sample program is a part \nof the WTL Library"), AtlLoadIcon(IDR_MAINFRAME));
+       return 0;
+}
+
+void CMainFrame::InitViews()
+{
+       // Get Desktop folder
+       CShellItemIDList spidl;
+       HRESULT hRet = ::SHGetSpecialFolderLocation(m_hWnd, CSIDL_DESKTOP, &spidl);
+       hRet;   // avoid level 4 warning
+       ATLASSERT(SUCCEEDED(hRet));
+
+       // Get system image lists
+       SHFILEINFO sfi = { 0 };
+       HIMAGELIST hImageList = (HIMAGELIST)::SHGetFileInfo(spidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_ICON);
+       ATLASSERT(hImageList != NULL);
+
+       memset(&sfi, 0, sizeof(SHFILEINFO));
+       HIMAGELIST hImageListSmall = (HIMAGELIST)::SHGetFileInfo(spidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
+       ATLASSERT(hImageListSmall != NULL);
+
+       // Set address bar combo box image list
+       m_wndCombo.SetImageList(hImageListSmall);
+
+       // Set tree view image list
+       m_wndTreeView.SetImageList(hImageListSmall, 0);
+
+       // Create list view columns
+       m_wndListView.InsertColumn(0, _T("Name"), LVCFMT_LEFT, 200, 0);
+       m_wndListView.InsertColumn(1, _T("Size"), LVCFMT_RIGHT, 100, 1);
+       m_wndListView.InsertColumn(2, _T("Type"), LVCFMT_LEFT, 100, 2);
+       m_wndListView.InsertColumn(3, _T("Modified"), LVCFMT_LEFT, 100, 3);
+       m_wndListView.InsertColumn(4, _T("Attributes"), LVCFMT_RIGHT, 100, 4);
+
+       // Set list view image lists
+       m_wndListView.SetImageList(hImageList, LVSIL_NORMAL);
+       m_wndListView.SetImageList(hImageListSmall, LVSIL_SMALL);
+}
diff --git a/include/WTL/Samples/WTLExplorer/ShellMgr.Cpp b/include/WTL/Samples/WTLExplorer/ShellMgr.Cpp
new file mode 100644 (file)
index 0000000..764475c
--- /dev/null
@@ -0,0 +1,173 @@
+// shellmgr.cpp
+
+#include "stdafx.h"
+#include <atlctrls.h>
+#include <atlctrlx.h>
+
+#include "shellmgr.h"
+#include "mainfrm.h"
+
+
+int CShellMgr::GetIconIndex(LPITEMIDLIST lpi, UINT uFlags)
+{
+       SHFILEINFO sfi = { 0 };
+       DWORD_PTR dwRet = ::SHGetFileInfo((LPCTSTR)lpi, 0, &sfi, sizeof(SHFILEINFO), uFlags);
+       return (dwRet != 0) ? sfi.iIcon : -1;
+}
+
+void CShellMgr::GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEM lptvitem)
+{
+       int nRet = lptvitem->iImage = GetIconIndex(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
+       ATLASSERT(nRet >= 0);
+       nRet = lptvitem->iSelectedImage = GetIconIndex(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON);
+       ATLASSERT(nRet >= 0);
+}
+
+LPITEMIDLIST CShellMgr::ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
+{
+       UINT cb1 = 0;
+       if (pidl1 != NULL)   // May be NULL
+               cb1 = GetSize(pidl1) - sizeof(pidl1->mkid.cb);
+
+       UINT cb2 = GetSize(pidl2);
+
+       LPITEMIDLIST pidlNew = (LPITEMIDLIST)::CoTaskMemAlloc(cb1 + cb2);
+       if (pidlNew != NULL)
+       {
+               if (pidl1 != NULL)
+                       memcpy(pidlNew, pidl1, cb1);
+
+               memcpy(((LPSTR)pidlNew) + cb1, pidl2, cb2);
+       }
+
+       return pidlNew;
+}
+
+BOOL CShellMgr::GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, DWORD dwFlags, LPTSTR lpFriendlyName)
+{
+       BOOL bSuccess = TRUE;
+       STRRET str = { STRRET_CSTR };
+
+       if (lpsf->GetDisplayNameOf(lpi, dwFlags, &str) == NOERROR)
+       {
+               USES_CONVERSION;
+
+               switch (str.uType)
+               {
+               case STRRET_WSTR:
+                       lstrcpy(lpFriendlyName, W2CT(str.pOleStr));
+                       ::CoTaskMemFree(str.pOleStr);
+                       break;
+               case STRRET_OFFSET:
+                       lstrcpy(lpFriendlyName, (LPTSTR)lpi + str.uOffset);
+                       break;
+               case STRRET_CSTR:
+                       lstrcpy(lpFriendlyName, A2CT(str.cStr));
+                       break;
+               default:
+                       bSuccess = FALSE;
+                       break;
+               }
+       }
+       else
+       {
+               bSuccess = FALSE;
+       }
+
+       return bSuccess;
+}
+
+LPITEMIDLIST CShellMgr::Next(LPCITEMIDLIST pidl)
+{
+       LPSTR lpMem = (LPSTR)pidl;
+       lpMem += pidl->mkid.cb;
+       return (LPITEMIDLIST)lpMem;
+}
+
+UINT CShellMgr::GetSize(LPCITEMIDLIST pidl)
+{
+       UINT cbTotal = 0;
+       if (pidl != NULL)
+       {
+               cbTotal += sizeof(pidl->mkid.cb);   // Null terminator
+               while (pidl->mkid.cb != NULL)
+               {
+                       cbTotal += pidl->mkid.cb;
+                       pidl = Next(pidl);
+               }
+       }
+
+       return cbTotal;
+}
+
+LPITEMIDLIST CShellMgr::CopyITEMID(LPITEMIDLIST lpi)
+{
+       LPITEMIDLIST lpiTemp = (LPITEMIDLIST)::CoTaskMemAlloc(lpi->mkid.cb + sizeof(lpi->mkid.cb));
+       ::CopyMemory((PVOID)lpiTemp, (CONST VOID*)lpi, lpi->mkid.cb + sizeof(lpi->mkid.cb));
+       return lpiTemp;
+}
+
+LPITEMIDLIST CShellMgr::GetFullyQualPidl(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi)
+{
+       TCHAR szBuff[MAX_PATH] = { 0 };
+
+       if (!GetName(lpsf, lpi, SHGDN_FORPARSING, szBuff))
+               return NULL;
+
+       CComPtr<IShellFolder> spDeskTop;
+       HRESULT hr = ::SHGetDesktopFolder(&spDeskTop);
+       if (FAILED(hr))
+               return NULL;
+
+       ULONG ulEaten = 0;
+       LPITEMIDLIST lpifq = NULL;
+       ULONG ulAttribs = 0;
+       USES_CONVERSION;
+       hr = spDeskTop->ParseDisplayName(NULL, NULL, T2W(szBuff), &ulEaten, &lpifq, &ulAttribs);
+
+       if (FAILED(hr))
+               return NULL;
+
+       return lpifq;
+}
+
+BOOL CShellMgr::DoContextMenu(HWND hWnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST lpi, POINT point)
+{
+       CComPtr<IContextMenu> spContextMenu;
+       HRESULT hr = lpsfParent->GetUIObjectOf(hWnd, 1, (const struct _ITEMIDLIST**)&lpi, IID_IContextMenu, 0, (LPVOID*)&spContextMenu);
+       if(FAILED(hr))
+               return FALSE;
+
+       HMENU hMenu = ::CreatePopupMenu();
+       if(hMenu == NULL)
+               return FALSE;
+
+       // Get the context menu for the item.
+       hr = spContextMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE);
+       if(FAILED(hr))
+               return FALSE;
+
+       int idCmd = ::TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
+
+       if (idCmd != 0)
+       {
+               USES_CONVERSION;
+
+               // Execute the command that was selected.
+               CMINVOKECOMMANDINFO cmi = { 0 };
+               cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
+               cmi.fMask = 0;
+               cmi.hwnd = hWnd;
+               cmi.lpVerb = T2CA(MAKEINTRESOURCE(idCmd - 1));
+               cmi.lpParameters = NULL;
+               cmi.lpDirectory = NULL;
+               cmi.nShow = SW_SHOWNORMAL;
+               cmi.dwHotKey = 0;
+               cmi.hIcon = NULL;
+               hr = spContextMenu->InvokeCommand(&cmi);
+       }
+
+       ::DestroyMenu(hMenu);
+
+       return TRUE;
+}
diff --git a/include/WTL/Samples/WTLExplorer/ShellMgr.H b/include/WTL/Samples/WTLExplorer/ShellMgr.H
new file mode 100644 (file)
index 0000000..bb0959b
--- /dev/null
@@ -0,0 +1,124 @@
+// shellmgr.h
+
+#ifndef __SHELLMGR_H__
+#define __SHELLMGR_H__
+
+#pragma once
+
+#include <shlobj.h>
+#include <atlctrls.h>
+
+
+class CShellItemIDList
+{
+public:
+       LPITEMIDLIST m_pidl;
+
+       CShellItemIDList(LPITEMIDLIST pidl = NULL) : m_pidl(pidl)
+       { }
+
+       ~CShellItemIDList()
+       {
+               ::CoTaskMemFree(m_pidl);
+       }
+
+       void Attach(LPITEMIDLIST pidl)
+       {
+               ::CoTaskMemFree(m_pidl);
+               m_pidl = pidl;
+       }
+
+       LPITEMIDLIST Detach()
+       {
+               LPITEMIDLIST pidl = m_pidl;
+               m_pidl = NULL;
+               return pidl;
+       }
+
+       bool IsNull() const
+       {
+               return (m_pidl == NULL);
+       }
+
+       CShellItemIDList& operator =(LPITEMIDLIST pidl)
+       {
+               Attach(pidl);
+               return *this;
+       }
+
+       LPITEMIDLIST* operator &()
+       {
+               return &m_pidl;
+       }
+
+       operator LPITEMIDLIST()
+       {
+               return m_pidl;
+       }
+
+       operator LPCTSTR()
+       {
+               return (LPCTSTR)m_pidl;
+       }
+
+       operator LPTSTR()
+       {
+               return (LPTSTR)m_pidl;
+       }
+
+       void CreateEmpty(UINT cbSize)
+       {
+               ::CoTaskMemFree(m_pidl);
+               m_pidl = (LPITEMIDLIST)::CoTaskMemAlloc(cbSize);
+               ATLASSERT(m_pidl != NULL);
+               if(m_pidl != NULL)
+                       memset(m_pidl, 0, cbSize);
+       }
+};
+
+
+typedef struct _LVItemData
+{
+       _LVItemData() : ulAttribs(0)
+       { }
+       
+       CComPtr<IShellFolder> spParentFolder;
+       
+       CShellItemIDList lpi;
+       ULONG ulAttribs;
+
+} LVITEMDATA, *LPLVITEMDATA;
+
+typedef struct _TVItemData
+{
+       _TVItemData()
+       { }
+       
+       CComPtr<IShellFolder> spParentFolder;
+       
+       CShellItemIDList lpi;
+       CShellItemIDList lpifq;
+
+} TVITEMDATA, *LPTVITEMDATA;
+
+
+class CShellMgr
+{
+public:
+       int GetIconIndex(LPITEMIDLIST lpi, UINT uFlags);
+
+       void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEM lptvitem);
+
+       LPITEMIDLIST ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
+
+       BOOL GetName (LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, DWORD dwFlags, LPTSTR lpFriendlyName);
+       LPITEMIDLIST Next(LPCITEMIDLIST pidl);
+       UINT GetSize(LPCITEMIDLIST pidl);
+       LPITEMIDLIST CopyITEMID(LPITEMIDLIST lpi);
+
+       LPITEMIDLIST GetFullyQualPidl(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi);
+
+       BOOL DoContextMenu(HWND hwnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST lpi, POINT point);
+};
+
+#endif //__SHELLMGR_H__
diff --git a/include/WTL/Samples/WTLExplorer/WTLExplorer.cpp b/include/WTL/Samples/WTLExplorer/WTLExplorer.cpp
new file mode 100644 (file)
index 0000000..048d158
--- /dev/null
@@ -0,0 +1,142 @@
+// WTLExplorer.cpp : main source file for WTLExplorer.exe
+//
+
+#include "stdafx.h"
+
+#include <atlframe.h>
+#include <atlctrls.h>
+#include <atldlgs.h>
+#include <atlctrlw.h>
+
+#include "resource.h"
+
+#include "mainfrm.h"
+
+CAppModule _Module;
+
+
+class CThreadManager
+{
+public:
+       // thread init param
+       struct _RunData
+       {
+               LPTSTR lpstrCmdLine;
+               int nCmdShow;
+       };
+
+       // thread proc
+       static DWORD WINAPI RunThread(LPVOID lpData)
+       {
+               CMessageLoop theLoop;
+               _Module.AddMessageLoop(&theLoop);
+
+               _RunData* pData = (_RunData*)lpData;
+               CMainFrame wndFrame;
+
+               if(wndFrame.CreateEx() == NULL)
+               {
+                       ATLTRACE(_T("Frame window creation failed!\n"));
+                       return 0;
+               }
+
+               wndFrame.ShowWindow(pData->nCmdShow);
+               ::SetForegroundWindow(wndFrame);        // Win95 needs this
+               delete pData;
+
+               int nRet = theLoop.Run();
+
+               _Module.RemoveMessageLoop();
+               return nRet;
+       }
+
+       DWORD m_dwCount;
+       HANDLE m_arrThreadHandles[MAXIMUM_WAIT_OBJECTS - 1];
+
+       CThreadManager() : m_dwCount(0)
+       { }
+
+// Operations
+       DWORD AddThread(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               if(m_dwCount == (MAXIMUM_WAIT_OBJECTS - 1))
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create ANY MORE threads!!!"), _T("WTLExplorer"), MB_OK);
+                       return 0;
+               }
+
+               _RunData* pData = new _RunData;
+               pData->lpstrCmdLine = lpstrCmdLine;
+               pData->nCmdShow = nCmdShow;
+               DWORD dwThreadID;
+               HANDLE hThread = ::CreateThread(NULL, 0, RunThread, pData, 0, &dwThreadID);
+               if(hThread == NULL)
+               {
+                       ::MessageBox(NULL, _T("ERROR: Cannot create thread!!!"), _T("WTLExplorer"), MB_OK);
+                       return 0;
+               }
+
+               m_arrThreadHandles[m_dwCount] = hThread;
+               m_dwCount++;
+               return dwThreadID;
+       }
+
+       void RemoveThread(DWORD dwIndex)
+       {
+               if(dwIndex != (m_dwCount - 1))
+                       m_arrThreadHandles[dwIndex] = m_arrThreadHandles[m_dwCount - 1];
+               m_dwCount--;
+       }
+
+       int Run(LPTSTR lpstrCmdLine, int nCmdShow)
+       {
+               MSG msg;
+               // force message queue to be created
+               ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+
+               AddThread(lpstrCmdLine, nCmdShow);
+
+               int nRet = m_dwCount;
+               DWORD dwRet;
+               while(m_dwCount > 0)
+               {
+                       dwRet = ::MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles, FALSE, INFINITE, QS_ALLINPUT);
+
+                       if(dwRet == 0xFFFFFFFF)
+                               ::MessageBox(NULL, _T("ERROR: Wait for multiple objects failed!!!"), _T("WTLExplorer"), MB_OK);
+                       else if(dwRet >= WAIT_OBJECT_0 && dwRet <= (WAIT_OBJECT_0 + m_dwCount - 1))
+                               RemoveThread(dwRet - WAIT_OBJECT_0);
+                       else if(dwRet == (WAIT_OBJECT_0 + m_dwCount))
+                       {
+                               ::GetMessage(&msg, NULL, 0, 0);
+                               if(msg.message == WM_USER)
+                                       AddThread(_T(""), SW_SHOWNORMAL);
+                               else
+                                       ::MessageBeep((UINT)-1);
+                       }
+                       else
+                               ::MessageBeep((UINT)-1);
+               }
+
+               return nRet;
+       }
+};
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
+{
+       HRESULT hRes = ::CoInitialize(NULL);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_USEREX_CLASSES);
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       CThreadManager mgr;
+       int nRet = mgr.Run(lpstrCmdLine, nCmdShow);
+
+       _Module.Term();
+       ::CoUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/Samples/WTLExplorer/mainfrm.h b/include/WTL/Samples/WTLExplorer/mainfrm.h
new file mode 100644 (file)
index 0000000..89e913e
--- /dev/null
@@ -0,0 +1,209 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __MAINFRM_H__
+#define __MAINFRM_H__
+
+#pragma once
+
+#include <atlframe.h>
+#include <atlsplit.h>
+#include <atlmisc.h>
+#include <atlctrls.h>
+#include <atlctrlw.h>
+#include <atlctrlx.h>
+
+#include "resource.h"
+
+#include "explorercombo.h"
+#include "shellmgr.h"
+
+
+class CMyPaneContainer : public CPaneContainerImpl<CMyPaneContainer>
+{
+public:
+       DECLARE_WND_CLASS_EX(_T("WtlExplorer_PaneContainer"), 0, -1)
+
+       void DrawPaneTitle(CDCHandle dc)
+       {
+               RECT rect = { 0 };
+               GetClientRect(&rect);
+
+               if(IsVertical())
+               {
+                       rect.right = rect.left + m_cxyHeader;
+                       dc.DrawEdge(&rect, EDGE_ETCHED, BF_LEFT | BF_TOP | BF_BOTTOM | BF_ADJUST);
+                       dc.FillRect(&rect, COLOR_3DFACE);
+               }
+               else
+               {
+                       rect.bottom = rect.top + m_cxyHeader;
+// we don't want this edge
+//                     dc.DrawEdge(&rect, EDGE_ETCHED, BF_LEFT | BF_TOP | BF_RIGHT | BF_ADJUST);
+                       dc.FillRect(&rect, COLOR_3DFACE);
+                       // draw title only for horizontal pane container
+                       dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
+                       dc.SetBkMode(TRANSPARENT);
+                       HFONT hFontOld = dc.SelectFont(GetTitleFont());
+                       rect.left += m_cxyTextOffset;
+                       rect.right -= m_cxyTextOffset;
+                       if(m_tb.m_hWnd != NULL)
+                               rect.right -= m_cxToolBar;;
+#ifndef _WIN32_WCE
+                       dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
+#else // CE specific
+                       dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
+#endif //_WIN32_WCE
+                       dc.SelectFont(hFontOld);
+               }
+       }
+};
+
+
+class CMainFrame : public CFrameWindowImpl<CMainFrame>, 
+                       public CUpdateUI<CMainFrame>,
+                       public CMessageFilter, 
+                       public CIdleHandler
+{
+private:
+       struct SortData
+       {
+               SortData(int nSortNum, bool bReverse) : nSort(nSortNum), bReverseSort(bReverse)
+               { }
+
+               int nSort;
+               bool bReverseSort;
+       };
+
+       CCommandBarCtrl m_wndCmdBar;
+       CSplitterWindow m_wndSplitter;
+///    CPaneContainer m_wndFolderTree;
+       CMyPaneContainer m_wndFolderTree;
+       CTreeViewCtrlEx m_wndTreeView;
+       CListViewCtrl m_wndListView;
+       CExplorerCombo m_wndCombo;
+
+       CShellMgr m_ShellMgr;
+
+       int m_nSort;
+       bool m_bReverseSort;
+
+       bool m_bFirstIdle;
+
+       // Buffer for OnLVGetDispInfo
+       TCHAR m_szListViewBuffer[MAX_PATH];
+public:
+       DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
+
+       CMainFrame() : m_nSort(0), m_bReverseSort(false), m_bFirstIdle(true)
+       { }
+
+       virtual BOOL PreTranslateMessage(MSG* pMsg)
+       {
+               return CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg);
+       }
+
+       virtual BOOL OnIdle()
+       {
+               if(m_bFirstIdle)
+               {
+                       CComPtr<IShellFolder> spFolder;
+                       HRESULT hr = ::SHGetDesktopFolder(&spFolder);
+                       if(SUCCEEDED(hr))
+                       {
+                               CWaitCursor wait;
+
+                               m_bFirstIdle = false;
+
+                               FillTreeView(spFolder, NULL, TVI_ROOT);
+                               m_wndTreeView.Expand(m_wndTreeView.GetRootItem());
+                               m_wndTreeView.SelectItem(m_wndTreeView.GetRootItem());
+                       }
+               }
+
+               UIUpdateToolBar();
+
+               return FALSE;
+       }
+
+       HWND CreateAddressBarCtrl(HWND hWndParent);
+
+       void InitViews();
+
+       HRESULT FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent);
+       static int CALLBACK CMainFrame::TreeViewCompareProc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort);
+
+       BOOL FillListView(LPTVITEMDATA lptvid, LPSHELLFOLDER pShellFolder);
+       static int CALLBACK ListViewCompareProc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort);
+
+       BEGIN_MSG_MAP(CMainFrame)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               COMMAND_RANGE_HANDLER(ID_VIEW_ICONS, ID_VIEW_LIST, OnViewChange)
+               COMMAND_RANGE_HANDLER(ID_VIEW_SORT_NAME, ID_VIEW_SORT_ATTR, OnViewSort)
+               COMMAND_ID_HANDLER(ID_COMBO_GO, OnComboGo)
+               COMMAND_ID_HANDLER(ID_VIEW_REFRESH, OnViewRefresh)
+
+               NOTIFY_CODE_HANDLER(NM_RCLICK, OnNMRClick)
+
+               NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnTVSelChanged)
+               NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING, OnTVItemExpanding)
+               NOTIFY_CODE_HANDLER(TVN_DELETEITEM, OnTVDeleteItem)
+
+               NOTIFY_CODE_HANDLER(LVN_GETDISPINFO, OnLVGetDispInfo)
+               NOTIFY_CODE_HANDLER(LVN_COLUMNCLICK, OnLVColumnClick)
+               NOTIFY_CODE_HANDLER(LVN_DELETEITEM, OnLVDeleteItem)
+               NOTIFY_CODE_HANDLER(NM_CLICK, OnLVItemClick)
+               NOTIFY_CODE_HANDLER(NM_DBLCLK, OnLVItemClick)
+
+               COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
+               COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
+               COMMAND_ID_HANDLER(ID_FILE_NEW_WINDOW, OnFileNewWindow)
+               COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
+               COMMAND_ID_HANDLER(ID_VIEW_ADDRESS_BAR, OnViewAddressBar)
+               COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
+               COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
+               CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
+               CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
+       END_MSG_MAP()
+
+       BEGIN_UPDATE_UI_MAP(CMainFrame)
+               UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_ADDRESS_BAR, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
+
+               UPDATE_ELEMENT(ID_VIEW_ICONS, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_SMALL_ICONS, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_LIST, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_DETAILS, UPDUI_MENUPOPUP)
+
+               UPDATE_ELEMENT(ID_VIEW_SORT_NAME, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_SORT_SIZE, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_SORT_TYPE, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_SORT_TIME, UPDUI_MENUPOPUP)
+               UPDATE_ELEMENT(ID_VIEW_SORT_ATTR, UPDUI_MENUPOPUP)
+       END_UPDATE_UI_MAP()
+
+       LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+       LRESULT OnViewChange(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnComboGo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnViewRefresh(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnViewSort(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnNMRClick(int , LPNMHDR pnmh, BOOL& );
+       LRESULT OnTVSelChanged(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/);
+       LRESULT OnTVItemExpanding(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/);
+       LRESULT OnTVDeleteItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/);
+       LRESULT OnLVGetDispInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/);
+       LRESULT OnLVColumnClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/);
+       LRESULT OnLVDeleteItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/);
+       LRESULT OnLVItemClick(int , LPNMHDR pnmh, BOOL& );
+       LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnFileNewWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnViewAddressBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+       LRESULT OnAppAbout(WORD, WORD, HWND , BOOL& );
+};
+
+#endif //__MAINFRM_H__
diff --git a/include/WTL/Samples/WTLExplorer/res/Toolbar.bmp b/include/WTL/Samples/WTLExplorer/res/Toolbar.bmp
new file mode 100644 (file)
index 0000000..dcb994a
Binary files /dev/null and b/include/WTL/Samples/WTLExplorer/res/Toolbar.bmp differ
diff --git a/include/WTL/Samples/WTLExplorer/res/WTLExplorer.ico b/include/WTL/Samples/WTLExplorer/res/WTLExplorer.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/Samples/WTLExplorer/res/WTLExplorer.ico differ
diff --git a/include/WTL/Samples/WTLExplorer/res/go.bmp b/include/WTL/Samples/WTLExplorer/res/go.bmp
new file mode 100644 (file)
index 0000000..ddfe904
Binary files /dev/null and b/include/WTL/Samples/WTLExplorer/res/go.bmp differ
diff --git a/include/WTL/Samples/WTLExplorer/res/idt_go1.bmp b/include/WTL/Samples/WTLExplorer/res/idt_go1.bmp
new file mode 100644 (file)
index 0000000..ad96ec2
Binary files /dev/null and b/include/WTL/Samples/WTLExplorer/res/idt_go1.bmp differ
diff --git a/include/WTL/Samples/WTLExplorer/resource.h b/include/WTL/Samples/WTLExplorer/resource.h
new file mode 100644 (file)
index 0000000..a4f68db
--- /dev/null
@@ -0,0 +1,31 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by WTLExplorer.rc
+//
+#define IDD_ABOUTBOX                    100
+#define ID_COMBO_GO                     101
+#define ID_VIEW_ICONS                   102
+#define ID_VIEW_DETAILS                 103
+#define ID_VIEW_SMALL_ICONS             104
+#define ID_VIEW_LIST                    105
+#define ID_VIEW_SORT_NAME               106
+#define ID_VIEW_SORT_SIZE               107
+#define ID_VIEW_SORT_TYPE               108
+#define ID_VIEW_SORT_TIME               109
+#define ID_VIEW_SORT_ATTR               110
+#define IDR_MAINFRAME                   128
+#define IDT_GO                          202
+#define IDT_GO1                         203
+#define ID_FILE_NEW_WINDOW              32771
+#define ID_VIEW_ADDRESS_BAR             32772
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32773
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/include/WTL/Samples/WTLExplorer/stdafx.cpp b/include/WTL/Samples/WTLExplorer/stdafx.cpp
new file mode 100644 (file)
index 0000000..83b4534
--- /dev/null
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     WTLExplorer.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
diff --git a/include/WTL/Samples/WTLExplorer/stdafx.h b/include/WTL/Samples/WTLExplorer/stdafx.h
new file mode 100644 (file)
index 0000000..7288216
--- /dev/null
@@ -0,0 +1,26 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#ifndef __STDAFX_H__
+#define __STDAFX_H__
+
+#pragma once
+
+// Change these values to use different versions
+#define WINVER         0x0400
+#define _WIN32_IE      0x0500
+#define _RICHEDIT_VER  0x0100
+
+#include <shlobj.h>
+#include <shlguid.h>
+
+#include <atlbase.h>
+#include <atlapp.h>
+
+extern CAppModule _Module;
+
+#include <atlwin.h>
+
+#endif //__STDAFX_H__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/FolderDialogStatusText.h b/include/WTL/Samples/Wizard97Test/Wizard/FolderDialogStatusText.h
new file mode 100644 (file)
index 0000000..7f2efe3
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef __FolderDialogStatusText_h__
+#define __FolderDialogStatusText_h__
+
+#pragma once
+
+#ifndef __cplusplus
+       #error ATL requires C++ compilation (use a .cpp suffix)
+#endif
+
+#ifndef __ATLAPP_H__
+       #error FolderDialogStatusText.h requires atlapp.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error FolderDialogStatusText.h requires atlwin.h to be included first
+#endif
+
+#ifndef __ATLWIN_H__
+       #error FolderDialogStatusText.h requires atlwin.h to be included first
+#endif
+
+#ifndef __ATLDLGS_H__
+       #error FolderDialogStatusText.h requires atldlgs.h to be included first
+#endif
+
+class CFolderDialogStatusText :
+       public CFolderDialogImpl<CFolderDialogStatusText>
+{
+protected:
+// Typedefs
+       typedef CFolderDialogImpl<CFolderDialogStatusText> baseClass;
+
+public:
+// Enumerations
+       enum DialogIds
+       {
+               // NOTE: Dialog IDs found using SPY++
+               _IDC_STATUSTEXT = 0x00003741,
+               _IDC_TITLE      = 0x00003742,
+       };
+
+// Constructor
+       CFolderDialogStatusText(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT)
+               : baseClass(hWndParent, lpstrTitle, uFlags)
+       {
+       }
+
+// Overrides from base class
+       void OnInitialized()
+       {
+               // NOTE: We compensate for the issue where BIF_STATUSTEXT
+               //  isn't honored if BIF_NEWDIALOGSTYLE is present.
+               //  Some would say its a bug, some would say its by design...
+               if((m_bi.ulFlags & BIF_NEWDIALOGSTYLE) == BIF_NEWDIALOGSTYLE &&
+                       (m_bi.ulFlags & BIF_STATUSTEXT) == BIF_STATUSTEXT)
+               {
+                       int fontHeight = 11;  // 8 point Tahoma at 96 DPI
+
+                       CWindow title = ::GetDlgItem(m_hWnd, _IDC_TITLE);
+                       RECT rcTitle = {0};
+                       if(title)
+                       {
+                               CFontHandle titleFont = title.GetFont();
+                               CLogFont logFont;
+                               titleFont.GetLogFont(logFont);
+                               if(logFont.lfHeight < 0)
+                                       fontHeight = -1*logFont.lfHeight;
+
+                               title.GetWindowRect(&rcTitle);
+                               ::MapWindowPoints(NULL, title.GetParent(), (LPPOINT)&rcTitle, 2);
+                               rcTitle.top -= 1;
+                               rcTitle.bottom -= fontHeight + 1;
+                               title.SetWindowPos(NULL, &rcTitle, (SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW));
+                       }
+
+                       CWindow status = ::GetDlgItem(m_hWnd, _IDC_STATUSTEXT);
+                       if(status)
+                       {
+                               status.EnableWindow(TRUE);
+                               status.ModifyStyle(0,SS_PATHELLIPSIS|SS_NOPREFIX);
+
+                               rcTitle.top = rcTitle.bottom + 2;
+                               rcTitle.bottom = rcTitle.top + fontHeight + (fontHeight/2);
+
+                               status.SetWindowPos(NULL, &rcTitle, (SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW));
+                       }
+
+                       // NOTE: We'd really like to have the status window resize appropriately
+                       //  when the dialog resizes, but currently that doesn't happen.
+               }
+       }
+
+       void OnSelChanged(LPITEMIDLIST pItemIDList)
+       {
+               if((m_bi.ulFlags & BIF_STATUSTEXT) == BIF_STATUSTEXT)
+               {
+                       TCHAR sNewFolder[MAX_PATH+1] = {0};
+                       if(::SHGetPathFromIDList(pItemIDList,sNewFolder))
+                       {
+                               if((m_bi.ulFlags & BIF_NEWDIALOGSTYLE) == BIF_NEWDIALOGSTYLE)
+                                       ::SetDlgItemText(m_hWnd, _IDC_STATUSTEXT, sNewFolder);
+                               else
+                                       this->SetStatusText(sNewFolder);
+                       }
+               }
+       }
+};
+
+#endif // __FolderDialogStatusText_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizard.cpp b/include/WTL/Samples/Wizard97Test/Wizard/TestWizard.cpp
new file mode 100644 (file)
index 0000000..f04f0ef
--- /dev/null
@@ -0,0 +1,214 @@
+
+#include "stdafx.h"
+#include "TestWizard.h"
+#include "TestWizardSheet.h"
+
+LPCTSTR g_lpcstrPrefRegKey = _T("Software\\Microsoft\\WTL Samples\\Wizard97Test");
+
+CTestWizard::CTestWizard()
+{
+}
+
+bool CTestWizard::ExecuteWizard()
+{
+       // You could also pass in parameters here
+       // (or something generic like a name/value map).
+
+       bool success = false;
+
+       this->InitializeDefaultValues();
+
+       CTestWizardSheet wizard(&m_testWizardInfo);
+       INT_PTR result = wizard.DoModal();
+       if(result == IDOK)
+       {
+               // You could either do the work here, or in
+               // OnWizardFinish in the completion page class.
+               success = true;
+
+               this->StoreDefaultValues();
+       }
+
+       return success;
+}
+
+void CTestWizard::InitializeDefaultValues()
+{
+       bool showWelcome = true;
+       CString defaultPath;
+       bool defaultRecurse = true;
+       CString defaultFilter;
+       TestWizardOutputType outputType = eOutput_Clipboard;
+       CString outputFileName;
+       TestWizardOutputFileEncoding outputFileEncoding = eEncoding_ASCII;
+
+       ATL::CRegKey regKey;
+       LONG result = regKey.Open(HKEY_CURRENT_USER, g_lpcstrPrefRegKey);
+       if(result == ERROR_SUCCESS)
+       {
+               this->GetBoolValue(regKey, _T("showWelcome"), showWelcome);
+               this->GetStringValue(regKey, _T("path"), defaultPath);
+               this->GetBoolValue(regKey, _T("recurse"), defaultRecurse);
+               this->GetStringValue(regKey, _T("filter"), defaultFilter);
+
+               CString outputTypeDisplayName;
+               if(this->GetStringValue(regKey, _T("outputType"), outputTypeDisplayName))
+               {
+                       CTestWizardInfo::GetOutputTypeForDisplayName(outputTypeDisplayName, outputType);
+
+                       // NOTE: We could have it so that "outputFileName" and "outputFileEncoding"
+                       //  were only looked for if the last output type were eOutput_SaveToFile.
+                       //  However, in case a previous run had done eOutput_SaveToFile, we'll
+                       //  load up what's there.
+
+                       //if(outputType == eOutput_SaveToFile)
+
+                       this->GetStringValue(regKey, _T("outputFileName"), outputFileName);
+
+                       CString outputFileEncodingDisplayName;
+                       if(this->GetStringValue(regKey, _T("outputFileEncoding"), outputFileEncodingDisplayName))
+                       {
+                               CTestWizardInfo::GetOutputFileEncodingForDisplayName(outputFileEncodingDisplayName, outputFileEncoding);
+                       }
+               }
+       }
+       regKey.Close();
+
+       if(defaultPath.IsEmpty())
+       {
+               ::GetCurrentDirectory(MAX_PATH, defaultPath.GetBuffer(MAX_PATH+1));
+               defaultPath.ReleaseBuffer();
+       }
+       if(defaultFilter.IsEmpty())
+       {
+               defaultFilter = _T("*.*");
+       }
+
+       m_testWizardInfo.SetShowWelcome(showWelcome);
+       m_testWizardInfo.SetPath(defaultPath);
+       m_testWizardInfo.SetRecurse(defaultRecurse);
+       m_testWizardInfo.SetFilter(defaultFilter);
+
+       m_testWizardInfo.SetOutputType(outputType);
+
+       m_testWizardInfo.SetOutputFileName(outputFileName);
+       m_testWizardInfo.SetOutputFileEncoding(outputFileEncoding);
+}
+
+void CTestWizard::StoreDefaultValues()
+{
+       bool showWelcome = m_testWizardInfo.GetShowWelcome();
+       CString path = m_testWizardInfo.GetPath();
+       bool recurse = m_testWizardInfo.GetRecurse();
+       CString filter = m_testWizardInfo.GetFilter();
+       TestWizardOutputType outputType = m_testWizardInfo.GetOutputType();
+       CString outputTypeDisplayName = m_testWizardInfo.GetOutputTypeDisplayName();
+
+       ATL::CRegKey regKey;
+       LONG result = regKey.Open(HKEY_CURRENT_USER, g_lpcstrPrefRegKey);
+       if(result != ERROR_SUCCESS)
+       {
+               result = regKey.Create(HKEY_CURRENT_USER, g_lpcstrPrefRegKey);
+       }
+       if(result == ERROR_SUCCESS)
+       {
+               this->SetBoolValue(regKey, _T("showWelcome"), showWelcome);
+               this->SetStringValue(regKey, _T("path"), path);
+               this->SetBoolValue(regKey, _T("recurse"), recurse);
+               this->SetStringValue(regKey, _T("filter"), filter);
+
+               // NOTE: For enumerations, we could either store the display name
+               //  or the enumeration value.  Which ever one you choose to store,
+               //  for future versions you either need to ensure that value 
+               //  never changes, or you need to do a conversion.  To do a conversion,
+               //  one way is to store a "schema version" number so that readers
+               //  know what you're written.
+               //
+               //  We'll choose to store the display name so that the enumeration
+               //  values can change (to change their order perhaps).
+               this->SetStringValue(regKey, _T("outputType"), outputTypeDisplayName);
+               if(outputType == eOutput_SaveToFile)
+               {
+                       CString outputFileName = m_testWizardInfo.GetOutputFileName();
+                       CString outputFileEncodingDisplayName = m_testWizardInfo.GetOutputFileEncodingDisplayName();
+
+                       this->SetStringValue(regKey, _T("outputFileName"), outputFileName);
+                       this->SetStringValue(regKey, _T("outputFileEncoding"), outputFileEncodingDisplayName);
+               }
+               else
+               {
+                       // Since "outputFileName" and "outputFileEncoding" are used with
+                       //  eOutput_SaveToFile, we could technically delete them if a previous
+                       //  run had stored them.  But we'll leave them in as defaults
+                       //  for future runs in case they switch back.
+                       //regKey.DeleteValue(_T("outputFileName"));
+                       //regKey.DeleteValue(_T("outputFileEncoding"));
+               }
+       }
+       regKey.Close();
+}
+
+bool CTestWizard::GetStringValue(ATL::CRegKey& regKey, LPCTSTR valueName, CString& value)
+{
+       bool success = false;
+
+#if (_ATL_VER >= 0x0700)
+       DWORD cchValue = 0;
+       LONG result = regKey.QueryStringValue(valueName, NULL, &cchValue);
+       if((result == ERROR_SUCCESS) && (cchValue > 0))
+       {
+               regKey.QueryStringValue(valueName, value.GetBuffer(cchValue+1), &cchValue);
+               value.ReleaseBuffer();
+               success = true;
+       }
+#else
+       DWORD cbValue = 0;
+       LONG result = regKey.QueryValue(NULL, valueName, &cbValue);
+       if((result == ERROR_SUCCESS) && (cbValue > 0))
+       {
+               regKey.QueryValue(value.GetBuffer((cbValue+1/sizeof(TCHAR))+1), valueName, &cbValue);
+               value.ReleaseBuffer();
+               success = true;
+       }
+#endif
+
+       return success;
+}
+
+bool CTestWizard::GetBoolValue(ATL::CRegKey& regKey, LPCTSTR valueName, bool& value)
+{
+       bool success = false;
+
+       DWORD dwValue = 0;
+#if (_ATL_VER >= 0x0700)
+       LONG result = regKey.QueryDWORDValue(valueName, dwValue);
+#else
+       LONG result = regKey.QueryValue(dwValue, valueName);
+#endif
+       if(result == ERROR_SUCCESS)
+       {
+               value = (dwValue != 0);
+               success = true;
+       }
+
+       return success;
+}
+
+bool CTestWizard::SetStringValue(ATL::CRegKey& regKey, LPCTSTR valueName, LPCTSTR value)
+{
+#if (_ATL_VER >= 0x0700)
+       return (ERROR_SUCCESS == regKey.SetStringValue(valueName, value, REG_SZ));
+#else
+       return (ERROR_SUCCESS == regKey.SetValue(value, valueName));
+#endif
+}
+
+bool CTestWizard::SetBoolValue(ATL::CRegKey& regKey, LPCTSTR valueName, bool value)
+{
+#if (_ATL_VER >= 0x0700)
+       return (ERROR_SUCCESS == regKey.SetDWORDValue(valueName, (value ? 1 : 0)));
+#else
+       return (ERROR_SUCCESS == regKey.SetValue((value ? 1 : 0), valueName));
+#endif
+}
+
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizard.h b/include/WTL/Samples/Wizard97Test/Wizard/TestWizard.h
new file mode 100644 (file)
index 0000000..d83a0c2
--- /dev/null
@@ -0,0 +1,30 @@
+
+#ifndef __TestWizard_h__
+#define __TestWizard_h__
+
+#include "TestWizardInfo.h"
+
+class CTestWizard
+{
+protected:
+// Data members
+       CTestWizardInfo m_testWizardInfo;
+
+public:
+// Constructors
+       CTestWizard();
+
+// General Methods
+       bool ExecuteWizard();
+
+       void InitializeDefaultValues();
+       void StoreDefaultValues();
+
+       bool GetStringValue(ATL::CRegKey& regKey, LPCTSTR valueName, CString& value);
+       bool GetBoolValue(ATL::CRegKey& regKey, LPCTSTR valueName, bool& value);
+
+       bool SetStringValue(ATL::CRegKey& regKey, LPCTSTR valueName, LPCTSTR value);
+       bool SetBoolValue(ATL::CRegKey& regKey, LPCTSTR valueName, bool value);
+};
+
+#endif // __TestWizard_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardCompletionPage.cpp b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardCompletionPage.cpp
new file mode 100644 (file)
index 0000000..bbd8bee
--- /dev/null
@@ -0,0 +1,158 @@
+
+#include "stdafx.h"
+#include "TestWizardCompletionPage.h"
+
+LRESULT CTestWizardCompletionPage::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       this->InitializeControls();
+       this->InitializeValues();
+
+       return 1;
+}
+
+void CTestWizardCompletionPage::InitializeFont(void)
+{
+       // Set the font
+       CLogFont logFont;
+       CClientDC dc(m_hWnd);
+       logFont.SetHeight(8, dc);
+       ::lstrcpy(logFont.lfFaceName, _T("Courier New"));
+
+       m_fontSummary.Attach(logFont.CreateFontIndirect());
+       m_editSummary.SetFont(m_fontSummary);
+
+       // Set the tab stops to 4 characters.
+       // Tab stops are in dialog units.
+       TEXTMETRIC tm = {0};
+       CFontHandle oldFont = dc.SelectFont(m_fontSummary);
+       dc.GetTextMetrics(&tm);
+       dc.SelectFont(oldFont);
+
+       int dialogUnitsX = ::MulDiv(4, tm.tmAveCharWidth, LOWORD(GetDialogBaseUnits()));
+       int tabStops = 4*dialogUnitsX;
+
+       m_editSummary.SetTabStops(tabStops);
+}
+
+void CTestWizardCompletionPage::InitializeControls(void)
+{
+       CFontHandle fontExteriorPageTitleFont(baseClass::GetExteriorPageTitleFont());
+
+       CWindow title = this->GetDlgItem(IDC_WIZ97_EXTERIOR_TITLE);
+       title.SetFont(fontExteriorPageTitleFont);
+
+       m_editSummary = this->GetDlgItem(IDC_WIZ97_SUMMARY);
+
+       this->InitializeFont();
+}
+
+void CTestWizardCompletionPage::InitializeValues(void)
+{
+}
+
+void CTestWizardCompletionPage::UpdateSummary(void)
+{
+       CString path = m_pTestWizardInfo->GetPath();
+       bool recurse = m_pTestWizardInfo->GetRecurse();
+       CString filter = m_pTestWizardInfo->GetFilter();
+       TestWizardOutputType outputType = m_pTestWizardInfo->GetOutputType();
+
+       CString text;
+       text.Format(
+               _T("Test Wizard: \r\n")
+               _T("· Find files in the directory:\r\n")
+               _T("\t%s\r\n")
+               _T("· %s\r\n")
+               _T("· Find files matching the filter '%s'\r\n"),
+               path,
+               recurse ? _T("Also search sub-directories") : _T("Only search that directory"),
+               filter);
+       m_editSummary.SetWindowText(text);
+
+       CString outputDescription;
+       switch(outputType)
+       {
+       case eOutput_SendEMail:
+               outputDescription = 
+                       _T("· Send the file list in an e-mail\r\n")
+                       _T("  (using the default mail client)\r\n");
+               break;
+       case eOutput_SaveToFile:
+               {
+                       CString outputFileName = m_pTestWizardInfo->GetOutputFileName();
+                       TestWizardOutputFileEncoding outputFileEncoding = m_pTestWizardInfo->GetOutputFileEncoding();
+
+                       outputDescription.Format(
+                               _T("· Save the file list to the file:\r\n")
+                               _T("\t%s\r\n"),
+                               outputFileName);
+                       switch(outputFileEncoding)
+                       {
+                       case eEncoding_ASCII:
+                               outputDescription += _T("  with ASCII encoding\r\n");
+                               break;
+                       case eEncoding_UCS2:
+                               outputDescription += _T("  with Unicode (UCS-2) encoding\r\n");
+                               break;
+                       case eEncoding_UTF8:
+                               outputDescription += _T("  with Unicode (UTF-8) encoding\r\n");
+                               break;
+                       }
+               }
+               break;
+       case eOutput_Clipboard:
+       default:
+               outputDescription = _T("· Copy the file list to the clipboard\r\n");
+               break;
+       }
+       m_editSummary.AppendText(outputDescription);
+}
+
+int CTestWizardCompletionPage::OnSetActive()
+{
+       this->SetWizardButtons(PSWIZB_BACK | PSWIZB_FINISH);
+
+       // Don't remember any previous updates to the summary,
+       //  and just regenerate the whole summary
+       this->UpdateSummary();
+
+       // 0 = allow activate
+       // -1 = go back to page that was active
+       // page ID = jump to page
+       return 0;
+}
+
+int CTestWizardCompletionPage::OnWizardBack()
+{
+       // 0  = goto previous page
+       // -1 = prevent page change
+       // >0 = jump to page by dlg ID
+       return m_pTestWizardInfo->FindPreviousPage(IDD);
+}
+
+INT_PTR CTestWizardCompletionPage::OnWizardFinish()
+{
+       // We could either do the work here, or in the place that
+       // called DoModal on our Sheet (which for this example is CTestWizard).
+       // The advantage of doing the work here is that we can prevent
+       // the finish, and tell the user to go back and correct something.
+       // The advantage of doing it in the caller of DoModal is
+       // that the wizard isn't visible while the work is being done.
+
+       // For this example, we'll do the work here (or rather call back into
+       // the info class to do the work), and prevent finish if something fails.
+
+       CWaitCursor waitCursor;
+
+       bool success = m_pTestWizardInfo->FinishWizard(m_hWnd);
+
+       // FALSE = allow finish
+       // TRUE = prevent finish
+       // HWND = prevent finish and set focus to HWND (CommCtrl 5.80 only)
+       return success ? FALSE : TRUE;
+}
+
+void CTestWizardCompletionPage::OnHelp()
+{
+       m_pTestWizardInfo->ShowHelp(IDD);
+}
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardCompletionPage.h b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardCompletionPage.h
new file mode 100644 (file)
index 0000000..f4d45e9
--- /dev/null
@@ -0,0 +1,49 @@
+
+#ifndef __TestWizardCompletionPage_h__
+#define __TestWizardCompletionPage_h__
+
+#include "TestWizardInfo.h"
+
+class CTestWizardCompletionPage :
+       public CWizard97ExteriorPageImpl<CTestWizardCompletionPage>,
+       public CTestWizardInfoRef
+{
+protected:
+// Typedefs
+       typedef CTestWizardCompletionPage thisClass;
+       typedef CWizard97ExteriorPageImpl<CTestWizardCompletionPage> baseClass;
+
+// Data members
+       CFont m_fontSummary;
+       CRichEditCtrl m_editSummary;
+
+public:
+// Constructors
+       CTestWizardCompletionPage(_U_STRINGorID title = (LPCTSTR)NULL) :
+               baseClass(title)
+       { }
+
+// Message Handlers
+       enum { IDD = IDD_WIZ97_COMPLETION };
+       BEGIN_MSG_MAP(thisClass)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+// Helpers
+       void InitializeFont(void);
+       void InitializeControls(void);
+       void InitializeValues(void);
+       void UpdateSummary(void);
+
+// Overrides from base class
+       int OnSetActive();
+       int OnWizardBack();
+       int OnWizardFinish();
+       void OnHelp();
+};
+
+#endif // __TestWizardCompletionPage_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardFilePreviewPage.cpp b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardFilePreviewPage.cpp
new file mode 100644 (file)
index 0000000..c056eb9
--- /dev/null
@@ -0,0 +1,385 @@
+
+#include "stdafx.h"
+#include "TestWizardFilePreviewPage.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// CFileListViewCtrl - a sortable list view of the resulting files
+
+LRESULT CFileListViewCtrl::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       LRESULT result = DefWindowProc();
+       if(result == -1)
+       {
+               return -1;
+       }
+
+       this->Initialize();
+       return result;
+}
+
+LRESULT CFileListViewCtrl::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+       this->Uninitialize();
+
+       bHandled = FALSE;
+       return 0;
+}
+
+LRESULT CFileListViewCtrl::OnContextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
+{
+       bHandled = TRUE;
+
+       int indexSelectedNearMenu = -1;
+
+       POINT ptPopup = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+       if(ptPopup.x == -1 && ptPopup.y == -1)
+       {
+               // They used the context menu key or Shift-F10 to bring up the context menu
+               indexSelectedNearMenu = this->GetNextItem(-1, LVNI_SELECTED);
+               RECT rect = {0};
+               if(indexSelectedNearMenu >= 0)
+               {
+                       // If there is a selected item, popup the menu under the first selected item,
+                       // if not, pop it up in the top left of the list view
+                       this->GetItemRect(indexSelectedNearMenu, &rect, LVIR_BOUNDS);
+                       ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rect, 2);
+                       ptPopup.x = rect.left;
+                       ptPopup.y = rect.bottom;
+               }
+       }
+       else
+       {
+               POINT ptClient = ptPopup;
+               ::MapWindowPoints(NULL, m_hWnd, &ptClient, 1);
+
+               LVHITTESTINFO hti = { 0 };
+               hti.pt = ptClient;
+               indexSelectedNearMenu = this->HitTest(&hti);
+       }
+
+       if(indexSelectedNearMenu > 0)
+       {
+               // TODO: Handle multiple selection
+               CString fullPath;
+               this->GetItemText(indexSelectedNearMenu, ListColumn_FullPath, fullPath);
+
+               // Build up the menu to show
+               //CMenu mnuContext;
+               //if(mnuContext.CreatePopupMenu())
+               //{
+               //}
+       }
+
+       return 0;
+}
+
+void CFileListViewCtrl::Initialize(void)
+{
+       this->InitializeListColumns();
+}
+
+void CFileListViewCtrl::InitializeListColumns(void)
+{
+       CRect rcList;
+       this->GetClientRect(&rcList);
+
+       int width = rcList.Width();
+       int columnWidth = 0;
+       int remainingWidth = width;
+
+       // NOTE: We'll take the default sort type (LVCOLSORT_TEXT)
+       // for the "Name" and "Folder" columns.
+       // LVCOLSORT_TEXT uses lstrcmp, which uses the currently
+       // selected user locale for sorting. This matches the sorting
+       // in the file list in Windows Explorer. With lstrcmp:
+       //    "a" < "A" and "A" < "b" and "b" < "B"
+       // By comparison, with _tcscmp the sort order is in "ASCII" order:
+       //    "A" < "a" and "Z" < "a"
+       // LVCOLSORT_TEXTNOCASE uses lstrcmpi, which sorts:
+       //    "a" == "A" and "A" < "b" and "b" == "B"
+
+       columnWidth = ::MulDiv(width, 20, 100);  // 20%
+       this->InsertColumn(ListColumn_Name, _T("Name"), LVCFMT_LEFT, columnWidth, ListColumn_Name);
+       //baseClass::SetColumnSortType(ListColumn_Name, LVCOLSORT_TEXT);
+       remainingWidth -= columnWidth;
+
+       columnWidth = ::MulDiv(width, 50, 100);  // 50%
+       this->InsertColumn(ListColumn_Folder, _T("In Folder"), LVCFMT_LEFT, columnWidth, ListColumn_Folder);
+       //baseClass::SetColumnSortType(ListColumn_Folder, LVCOLSORT_TEXT);
+       remainingWidth -= columnWidth;
+
+       columnWidth = ::MulDiv(width, 15, 100);  // 15%
+       this->InsertColumn(ListColumn_LastModified, _T("Date Modified"), LVCFMT_LEFT, columnWidth, ListColumn_LastModified);
+       baseClass::SetColumnSortType(ListColumn_LastModified, LVCOLSORT_DATETIME);
+       remainingWidth -= columnWidth;
+
+       columnWidth = remainingWidth;
+       this->InsertColumn(ListColumn_Size, _T("Size"), LVCFMT_LEFT, columnWidth, ListColumn_Size);
+       baseClass::SetColumnSortType(ListColumn_Size, LVCOLSORT_CUSTOM);
+
+       // Hidden columns
+       // (We could go to more work to keep these truly hidden,
+       //  but for now, we'll allow column size adjusts, Ctrl+NumPad+
+       //  and the like to reveal the columns).
+       this->InsertColumn(ListColumn_SizeBytes, _T("Size in Bytes"), LVCFMT_LEFT, 0, ListColumn_SizeBytes);
+       baseClass::SetColumnSortType(ListColumn_SizeBytes, LVCOLSORT_DECIMAL);
+
+       this->InsertColumn(ListColumn_FullPath, _T("Full Path"), LVCFMT_LEFT, 0, ListColumn_FullPath);
+       //baseClass::SetColumnSortType(ListColumn_FullPath, LVCOLSORT_TEXT);
+}
+
+void CFileListViewCtrl::Uninitialize(void)
+{
+}
+
+BOOL CFileListViewCtrl::SubclassWindow(HWND hWnd)
+{
+       ATLASSERT(m_hWnd == NULL);
+       ATLASSERT(::IsWindow(hWnd));
+       BOOL returnValue = baseClass::SubclassWindow(hWnd);
+       if(returnValue)
+       {
+               this->Initialize();
+       }
+       return returnValue;
+}
+
+HWND CFileListViewCtrl::UnsubclassWindow(BOOL bForce)
+{
+       this->Uninitialize();
+
+       return baseClass::UnsubclassWindow(bForce);
+}
+
+int CFileListViewCtrl::CompareItemsCustom(LVCompareParam* pItem1, LVCompareParam* pItem2, int iSortCol)
+{
+       int result = 0;
+
+       // Deal with all of the custom sort columns
+       switch(iSortCol)
+       {
+       case ListColumn_Size:
+               {
+                       // Sort based on ListColumn_SizeBytes
+
+                       // NOTE: There's other ways to use a "proxy column" for sorting, this is just one
+                       //  (mainly, just to give an example of CompareItemsCustom).
+                       //  Another way would be to have DoSortItems run on the hidden column,
+                       //  but then SetSortColumn for the visible column.
+
+                       CString sizeInBytesLHS, sizeInBytesRHS;
+                       this->GetItemText(pItem1->iItem, ListColumn_SizeBytes, sizeInBytesLHS);
+                       this->GetItemText(pItem2->iItem, ListColumn_SizeBytes, sizeInBytesRHS);
+
+                       __int64 difference = _ttoi64(sizeInBytesRHS) - _ttoi64(sizeInBytesLHS);
+                       if(difference < 0)
+                               result = 1;
+                       else if(difference > 0)
+                               result = -1;
+                       else
+                               result = 0;
+               }
+               break;
+       }
+
+       return result;
+}
+
+void CFileListViewCtrl::OnFileFound(LPCTSTR directory, LPWIN32_FIND_DATA findFileData)
+{
+       TCHAR fileFullPath[MAX_PATH+1] = {0};
+       ::PathCombine(fileFullPath, directory, findFileData->cFileName);
+
+       ULARGE_INTEGER fileSize = { findFileData->nFileSizeLow, findFileData->nFileSizeHigh };
+
+       this->AddFile(directory, findFileData->cFileName, fileFullPath, findFileData->ftLastWriteTime, fileSize.QuadPart);
+}
+
+int CFileListViewCtrl::AddFile(LPCTSTR fileFullPath)
+{
+       int index = -1;
+
+       WIN32_FILE_ATTRIBUTE_DATA attributes = {0};
+       if(::GetFileAttributesEx(fileFullPath, GetFileExInfoStandard, &attributes))
+       {
+               TCHAR fileSpec[MAX_PATH+1] = {0};
+               TCHAR directory[MAX_PATH+1] = {0};
+
+               ::lstrcpyn(fileSpec, fileFullPath, MAX_PATH);
+               ::lstrcpyn(directory, fileFullPath, MAX_PATH);
+
+               ::PathStripPath(fileSpec);
+               ::PathRemoveFileSpec(directory);
+
+               ULARGE_INTEGER fileSize = { attributes.nFileSizeLow, attributes.nFileSizeHigh };
+
+               index = this->AddFile(directory, fileSpec, fileFullPath, attributes.ftLastWriteTime, fileSize.QuadPart);
+       }
+
+       return index;
+}
+
+int CFileListViewCtrl::AddFile(LPCTSTR directory, LPCTSTR fileSpec, LPCTSTR fileFullPath, FILETIME lastWriteTimeUTC, ULONGLONG fileSize)
+{
+       FILETIME localTime = {0};
+       SYSTEMTIME st = {0};
+       ::FileTimeToLocalFileTime(&lastWriteTimeUTC, &localTime);
+       ::FileTimeToSystemTime(&localTime, &st);
+
+       int hour12 = st.wHour;
+       if(st.wHour == 0)
+               hour12 = 12;
+       else if(st.wHour > 12)
+               hour12 -= 12;
+
+       CString lastModified;
+       lastModified.Format(_T("%d/%d/%d %d:%.2d %s"),
+               st.wMonth, st.wDay, st.wYear,
+               hour12, st.wMinute, (st.wHour > 11) ? _T("PM") : _T("AM"));
+
+       TCHAR size[32] = {0};
+       ::StrFormatByteSize64(fileSize, size, 31);
+
+       CString sizeBytes;
+       sizeBytes.Format(_T("%I64u"), fileSize);
+
+       int index = this->GetItemCount();
+       this->InsertItem(index, fileSpec);
+       this->SetItemText(index, ListColumn_Folder, directory);
+       this->SetItemText(index, ListColumn_LastModified, lastModified);
+       this->SetItemText(index, ListColumn_Size, size);
+       this->SetItemText(index, ListColumn_SizeBytes, sizeBytes);
+       this->SetItemText(index, ListColumn_FullPath, fileFullPath);
+
+       return index;
+}
+
+void CFileListViewCtrl::AutoResizeColumns(void)
+{
+       this->SetColumnWidth(ListColumn_Name, LVSCW_AUTOSIZE_USEHEADER);
+       this->SetColumnWidth(ListColumn_Folder, LVSCW_AUTOSIZE_USEHEADER);
+       this->SetColumnWidth(ListColumn_LastModified, LVSCW_AUTOSIZE_USEHEADER);
+       this->SetColumnWidth(ListColumn_Size, LVSCW_AUTOSIZE_USEHEADER);
+       this->SetColumnWidth(ListColumn_SizeBytes, 0);
+       this->SetColumnWidth(ListColumn_FullPath, 0);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTestWizardFilePreviewPage - Wizard page to preview the files located by the path/filter
+
+LRESULT CTestWizardFilePreviewPage::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CWaitCursor waitCursor;
+
+       this->InitializeControls();
+       this->InitializeValues();
+
+       return 1;
+}
+
+LRESULT CTestWizardFilePreviewPage::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+       // Be sure the base gets the message too
+       bHandled = FALSE;
+
+       this->UninitializeControls();   
+       return 0;
+}
+
+LRESULT CTestWizardFilePreviewPage::OnClickPreview(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CWaitCursor waitCursor;
+
+       m_listFiles.EnableWindow(TRUE);
+
+       this->UpdateFileList();
+
+       return 0;
+}
+
+void CTestWizardFilePreviewPage::InitializeControls(void)
+{
+       m_listFiles.SubclassWindow(this->GetDlgItem(IDC_LIST_FILES));
+
+       m_buttonPreview = this->GetDlgItem(IDC_BTN_PREVIEW);
+
+       m_listFiles.EnableWindow(FALSE);
+}
+
+void CTestWizardFilePreviewPage::UninitializeControls(void)
+{
+       m_listFiles.UnsubclassWindow();
+}
+
+void CTestWizardFilePreviewPage::InitializeValues(void)
+{
+       m_listFiles.DeleteAllItems();
+}
+
+bool CTestWizardFilePreviewPage::StoreValues(void)
+{
+       return true;
+}
+
+void CTestWizardFilePreviewPage::UpdateFileList()
+{
+       CWaitCursor waitCursor;
+
+       m_listFiles.SetSortColumn(-1);
+
+       m_listFiles.SetRedraw(FALSE);
+       m_listFiles.DeleteAllItems();
+
+       int fileCount = m_pTestWizardInfo->FindFiles(&m_listFiles);
+
+       if(fileCount < 1)
+       {
+               m_listFiles.InsertItem(0, _T("(No existing files found for the path and filter)"));
+       }
+
+       m_listFiles.AutoResizeColumns();
+
+       m_listFiles.SetRedraw(TRUE);
+       m_listFiles.Invalidate();
+}
+
+// Overrides from base class
+int CTestWizardFilePreviewPage::OnSetActive()
+{
+       m_listFiles.EnableWindow(FALSE);
+
+       this->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
+
+       // 0 = allow activate
+       // -1 = go back to page that was active
+       // page ID = jump to page
+       return 0;
+}
+
+int CTestWizardFilePreviewPage::OnWizardNext()
+{
+       bool success = this->StoreValues();
+       if(!success)
+       {
+               // Any errors are already reported, and if appropriate,
+               // the control that needs attention has been given focus.
+               return -1;
+       }
+
+       // 0  = goto next page
+       // -1 = prevent page change
+       // >0 = jump to page by dlg ID
+
+       return m_pTestWizardInfo->FindNextPage(IDD);
+}
+
+int CTestWizardFilePreviewPage::OnWizardBack()
+{
+       return m_pTestWizardInfo->FindPreviousPage(IDD);
+}
+
+void CTestWizardFilePreviewPage::OnHelp()
+{
+       m_pTestWizardInfo->ShowHelp(IDD);
+}
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardFilePreviewPage.h b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardFilePreviewPage.h
new file mode 100644 (file)
index 0000000..743fba8
--- /dev/null
@@ -0,0 +1,139 @@
+
+#ifndef __TestWizardFilePreviewPage_h__
+#define __TestWizardFilePreviewPage_h__
+
+#include "TestWizardInfo.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// CFileListViewCtrl - a sortable list view of the resulting files
+
+typedef CWinTraits<
+                       WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
+                       LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS,
+                       WS_EX_CLIENTEDGE> CFileListViewCtrlWinTraits;
+
+class CFileListViewCtrl :
+       public CSortListViewCtrlImpl<CFileListViewCtrl, CListViewCtrl, CFileListViewCtrlWinTraits>,
+       public ITestWizardFindFileCB
+{
+protected:
+// Typedefs
+       typedef CFileListViewCtrl thisClass;
+       typedef CSortListViewCtrlImpl<CFileListViewCtrl, CListViewCtrl, CFileListViewCtrlWinTraits> baseClass;
+
+public:
+// Enumerations
+       enum ListColumnIndex
+       {
+               ListColumn_Name         = 0,
+               ListColumn_Folder       = 1,
+               ListColumn_LastModified = 2,
+               ListColumn_Size         = 3,
+               ListColumn_SizeBytes    = 4,
+               ListColumn_FullPath     = 5,
+       };
+
+// Message Handling
+       DECLARE_WND_SUPERCLASS(_T("FileListView"), CListViewCtrl::GetWndClassName())
+
+       BEGIN_MSG_MAP(thisClass)
+               MESSAGE_HANDLER(WM_CREATE, OnCreate)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+               MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
+
+               CHAIN_MSG_MAP(baseClass)
+               DEFAULT_REFLECTION_HANDLER()
+       END_MSG_MAP()
+
+       LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+       LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+       LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+// Helpers
+       void Initialize(void);
+       void InitializeListColumns(void);
+       void Uninitialize(void);
+
+// Overrides for CWindowImpl
+       BOOL SubclassWindow(HWND hWnd);
+       HWND UnsubclassWindow(BOOL bForce = FALSE);
+
+// Overrides for CSortListViewImpl
+       int CompareItemsCustom(LVCompareParam* pItem1, LVCompareParam* pItem2, int iSortCol);
+
+// ITestWizardFindFileCB
+       virtual bool OnBeginFindFiles(void) { return true; }
+       virtual void OnEndFindFiles(void) { }
+       virtual bool OnBeginDirectorySearch(LPCTSTR /*directory*/) { return true; }
+       virtual void OnEndDirectorySearch(LPCTSTR /*directory*/) { }
+       virtual void OnFileFound(LPCTSTR directory, LPWIN32_FIND_DATA findFileData);
+
+// Methods
+       int AddFile(LPCTSTR fileFullPath);
+       int AddFile(LPCTSTR directory, LPCTSTR fileSpec, LPCTSTR fileFullPath, FILETIME lastWriteTimeUTC, ULONGLONG fileSize);
+       void AutoResizeColumns(void);
+       void ClearSortHeaderBitmap(void);
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CTestWizardFilePreviewPage - Wizard page to preview the files located by the path/filter
+
+class CTestWizardFilePreviewPage :
+       public CWizard97InteriorPageImpl<CTestWizardFilePreviewPage>,
+       public CTestWizardInfoRef
+{
+protected:
+// Typedefs
+       typedef CTestWizardFilePreviewPage thisClass;
+       typedef CWizard97InteriorPageImpl<CTestWizardFilePreviewPage> baseClass;
+
+// Data members
+       CFileListViewCtrl m_listFiles;
+
+       CButton m_buttonPreview;
+
+public:
+// Constructor
+       CTestWizardFilePreviewPage(_U_STRINGorID title = (LPCTSTR)NULL) :
+               baseClass(title)
+       {
+               baseClass::SetHeaderTitle(_T("Preview File List"));
+               baseClass::SetHeaderSubTitle(_T("Preview the list of files identified by the path and filter."));
+       }
+
+// Message Handlers
+       enum { IDD = IDD_WIZ97_FILEPREVIEW };
+       BEGIN_MSG_MAP(thisClass)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+
+               COMMAND_HANDLER(IDC_BTN_PREVIEW, BN_CLICKED, OnClickPreview)
+
+               CHAIN_MSG_MAP(baseClass)
+               REFLECT_NOTIFICATIONS_ID_FILTERED(IDC_LIST_FILES)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+       LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+       LRESULT OnClickPreview(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+
+// Helpers
+       void InitializeControls(void);
+       //void InitializeControlSizes(void);
+       void UninitializeControls(void);
+       void InitializeValues(void);
+       bool StoreValues(void);
+
+       void UpdateFileList();
+
+// Overrides from base class
+       int OnSetActive();
+       int OnWizardNext();
+       int OnWizardBack();
+       void OnHelp();
+
+};
+
+#endif // __TestWizardFilePreviewPage_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardInfo.cpp b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardInfo.cpp
new file mode 100644 (file)
index 0000000..9578598
--- /dev/null
@@ -0,0 +1,693 @@
+
+#include "stdafx.h"
+#include "TestWizardInfo.h"
+
+#include <HtmlHelp.h>
+#include <mapi.h>
+
+// NOTE: These "Display Name" string arrays depends on the enumeration
+//  value corresponding to the index into the array.
+static LPCTSTR s_testWizardOutputTypeDisplayName[eOutput_Last+1] = {
+       _T("Copy to Clipboard"),
+       _T("Send e-mail"),
+       _T("Save to file"),
+};
+
+static LPCTSTR s_testWizardOutputFileEncodingDisplayName[eEncoding_Last+1] = {
+       _T("ASCII"),
+       _T("Unicode (UCS-2)"),
+       _T("Unicode (UTF-8)"),
+};
+
+CTestWizardInfo::CTestWizardInfo() :
+       m_showWelcome(false),
+       m_recurse(false),
+       m_filter(s_allFiles),
+       m_outputFileEncoding(eEncoding_ASCII)
+{
+}
+
+CTestWizardInfo::~CTestWizardInfo()
+{
+}
+
+// Set
+bool CTestWizardInfo::SetShowWelcome(bool showWelcome)
+{
+       m_showWelcome = showWelcome;
+       return (m_showWelcome == showWelcome);
+}
+
+bool CTestWizardInfo::SetPath(LPCTSTR path)
+{
+       m_path = path;
+       return (m_path == path);
+}
+
+bool CTestWizardInfo::SetRecurse(bool recurse)
+{
+       m_recurse = recurse;
+       return (m_recurse == recurse);
+}
+
+bool CTestWizardInfo::SetFilter(LPCTSTR filter)
+{
+       m_filter = filter;
+       return (m_filter == filter);
+}
+
+bool CTestWizardInfo::SetOutputType(TestWizardOutputType outputType)
+{
+       m_outputType = outputType;
+       return (m_outputType == outputType);
+}
+
+bool CTestWizardInfo::SetOutputTypeByDisplayName(LPCTSTR typeDisplayName)
+{
+       return thisClass::GetOutputTypeForDisplayName(typeDisplayName, m_outputType);
+}
+
+bool CTestWizardInfo::SetOutputFileName(LPCTSTR outputFileName)
+{
+       m_outputFileName = outputFileName;
+       return (m_outputFileName == outputFileName);
+}
+
+bool CTestWizardInfo::SetOutputFileEncoding(TestWizardOutputFileEncoding outputFileEncoding)
+{
+       m_outputFileEncoding = outputFileEncoding;
+       return (m_outputFileEncoding == outputFileEncoding);
+}
+
+bool CTestWizardInfo::SetOutputFileEncodingByDisplayName(LPCTSTR encodingDisplayName)
+{
+       return thisClass::GetOutputFileEncodingForDisplayName(encodingDisplayName, m_outputFileEncoding);
+}
+
+// Get
+bool CTestWizardInfo::GetShowWelcome(void) const
+{
+       return m_showWelcome;
+}
+
+CString CTestWizardInfo::GetPath(void) const
+{
+       return m_path;
+}
+
+bool CTestWizardInfo::GetRecurse(void) const
+{
+       return m_recurse;
+}
+
+CString CTestWizardInfo::GetFilter(void) const
+{
+       return m_filter;
+}
+
+TestWizardOutputType CTestWizardInfo::GetOutputType(void) const
+{
+       return m_outputType;
+}
+
+CString CTestWizardInfo::GetOutputTypeDisplayName(void) const
+{
+       return thisClass::GetOutputTypeDisplayName(m_outputType);
+}
+
+CString CTestWizardInfo::GetOutputFileName(void) const
+{
+       return m_outputFileName;
+}
+
+TestWizardOutputFileEncoding CTestWizardInfo::GetOutputFileEncoding(void) const
+{
+       return m_outputFileEncoding;
+}
+
+CString CTestWizardInfo::GetOutputFileEncodingDisplayName(void) const
+{
+       return thisClass::GetOutputFileEncodingDisplayName(m_outputFileEncoding);
+}
+
+// Static methods
+bool CTestWizardInfo::IsValidOutputType(DWORD outputType)
+{
+       return ((outputType >= (DWORD)eOutput_First) && (outputType <= (DWORD)eOutput_Last));
+}
+
+bool CTestWizardInfo::IsValidOutputFileEncoding(DWORD outputFileEncoding)
+{
+       return ((outputFileEncoding >= (DWORD)eEncoding_First) && (outputFileEncoding <= (DWORD)eEncoding_Last));
+}
+
+CString CTestWizardInfo::GetOutputTypeDisplayName(TestWizardOutputType outputType)
+{
+       CString typeDisplayName;
+
+       ATLASSERT(thisClass::IsValidOutputType((DWORD)outputType));
+       if(thisClass::IsValidOutputType((DWORD)outputType))
+       {
+               typeDisplayName = s_testWizardOutputTypeDisplayName[outputType];
+       }
+
+       return typeDisplayName;
+}
+
+CString CTestWizardInfo::GetOutputFileEncodingDisplayName(TestWizardOutputFileEncoding outputFileEncoding)
+{
+       CString encodingDisplayName;
+
+       ATLASSERT(thisClass::IsValidOutputFileEncoding((DWORD)outputFileEncoding));
+       if(thisClass::IsValidOutputFileEncoding((DWORD)outputFileEncoding))
+       {
+               encodingDisplayName = s_testWizardOutputFileEncodingDisplayName[outputFileEncoding];
+       }
+
+       return encodingDisplayName;
+}
+
+bool CTestWizardInfo::GetOutputTypeForDisplayName(LPCTSTR typeDisplayName, TestWizardOutputType& outputType)
+{
+       bool success = false;
+
+       ATLASSERT(typeDisplayName != NULL);
+       if(typeDisplayName != NULL)
+       {
+               for(int i=(int)eOutput_First; i<=(int)eOutput_Last && !success; ++i)
+               {
+                       if(::lstrcmpi(typeDisplayName, s_testWizardOutputTypeDisplayName[i]) == 0)
+                       {
+                               outputType = (TestWizardOutputType)i;
+                               success = true;
+                       }
+               }
+       }
+
+       return success;
+}
+
+bool CTestWizardInfo::GetOutputFileEncodingForDisplayName(LPCTSTR encodingDisplayName, TestWizardOutputFileEncoding& outputFileEncoding)
+{
+       bool success = false;
+
+       ATLASSERT(encodingDisplayName != NULL);
+       if(encodingDisplayName != NULL)
+       {
+               for(int i=(int)eEncoding_First; i<=(int)eEncoding_Last && !success; ++i)
+               {
+                       if(::lstrcmpi(encodingDisplayName, s_testWizardOutputFileEncodingDisplayName[i]) == 0)
+                       {
+                               outputFileEncoding = (TestWizardOutputFileEncoding)i;
+                               success = true;
+                       }
+               }
+       }
+
+       return success;
+}
+
+// File List
+int CTestWizardInfo::FindFiles(ITestWizardFindFileCB* callback) const
+{
+       ATLASSERT(callback != NULL);
+       if(callback == NULL)
+       {
+               return 0;
+       }
+
+       int fileCount = 0;
+
+       bool success = callback->OnBeginFindFiles();
+       if(success)
+       {
+               fileCount = this->FindFiles(callback, m_path, m_filter, m_recurse);
+
+               callback->OnEndFindFiles();
+       }
+
+       return fileCount;
+}
+
+int CTestWizardInfo::FindFiles(ITestWizardFindFileCB* callback, LPCTSTR directory, LPCTSTR filter, bool recurse) const
+{
+       int fileCount = 0;
+
+       bool success = callback->OnBeginDirectorySearch(directory);
+       if(success)
+       {
+               // First search current directory for files specified by the filter
+
+               TCHAR directoryWithFilter[MAX_PATH] = {0};
+               ::PathCombine(directoryWithFilter, directory, filter);
+
+               WIN32_FIND_DATA findFileData = {0};
+               HANDLE hFindFile = ::FindFirstFile(directoryWithFilter, &findFileData);
+               if(hFindFile != INVALID_HANDLE_VALUE)
+               {
+                       do
+                       {
+                               if(FILE_ATTRIBUTE_DIRECTORY != (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+                               {
+                                       fileCount += 1;
+
+                                       callback->OnFileFound(directory, &findFileData);
+                               }
+                       } while(TRUE == ::FindNextFile(hFindFile, &findFileData));
+
+                       ::FindClose(hFindFile);
+                       hFindFile = NULL;
+               }
+
+               // Then recurse sub-directories if appropriate
+               if(recurse)
+               {
+                       ::PathCombine(directoryWithFilter, directory, _T("*"));
+
+                       HANDLE hFindDirectory = NULL;
+                       WIN32_FIND_DATA findDirectoryData = {0};
+                       hFindDirectory = ::FindFirstFileEx(directoryWithFilter, FindExInfoStandard, &findDirectoryData, FindExSearchLimitToDirectories, NULL, 0);
+                       if(hFindDirectory != INVALID_HANDLE_VALUE)
+                       {
+                               TCHAR subDirectory[MAX_PATH] = {0};
+
+                               do
+                               {
+                                       if(     FILE_ATTRIBUTE_DIRECTORY == (findDirectoryData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+                                               ::lstrcmp(_T("."), findDirectoryData.cFileName) != 0 &&
+                                               ::lstrcmp(_T(".."), findDirectoryData.cFileName) != 0)
+                                       {
+                                               ::PathCombine(subDirectory, directory, findDirectoryData.cFileName);
+
+                                               fileCount += this->FindFiles(callback, subDirectory, filter, recurse);
+                                       }
+                               } while(TRUE == ::FindNextFile(hFindDirectory, &findDirectoryData));
+
+                               ::FindClose(hFindDirectory);
+                               hFindDirectory = NULL;
+                       }
+               }
+
+               callback->OnEndDirectorySearch(directory);
+       }
+
+       return fileCount;
+}
+
+int CTestWizardInfo::FindPreviousPage(int /*pageDialogId*/) const
+{
+       // 0  = goto previous page
+       // -1 = prevent page change
+       // >0 = jump to page by dlg ID
+       int page = 0;
+
+       //switch(pageDialogId)
+       //{
+       //case IDD_WIZ97_WELCOME:
+       //      break;
+       //case IDD_WIZ97_PATHFILTER:
+       //      break;
+       //case IDD_WIZ97_FILEPREVIEW:
+       //      break;
+       //case IDD_WIZ97_OUTPUT:
+       //      break;
+       //case IDD_WIZ97_COMPLETION:
+       //      break;
+       //}
+
+       return page;
+}
+
+int CTestWizardInfo::FindNextPage(int /*pageDialogId*/) const
+{
+       // 0  = goto next page
+       // -1 = prevent page change
+       // >0 = jump to page by dlg ID
+       int page = 0;
+
+       //switch(pageDialogId)
+       //{
+       //case IDD_WIZ97_WELCOME:
+       //      break;
+       //case IDD_WIZ97_PATHFILTER:
+       //      break;
+       //case IDD_WIZ97_FILEPREVIEW:
+       //      break;
+       //case IDD_WIZ97_OUTPUT:
+       //      break;
+       //case IDD_WIZ97_COMPLETION:
+       //      break;
+       //}
+
+       return page;
+}
+
+void CTestWizardInfo::ShowHelp(int pageDialogId, int /*controlId*/)
+{
+       LPCTSTR topicPath = NULL;
+
+       switch(pageDialogId)
+       {
+       case IDD_WIZ97_WELCOME:
+               topicPath = _T("/TestWizard_Welcome.html");
+               break;
+       case IDD_WIZ97_PATHFILTER:
+               topicPath = _T("/TestWizard_PathFilter.html");
+               break;
+       case IDD_WIZ97_FILEPREVIEW:
+               topicPath = _T("/TestWizard_PreviewFileList.html");
+               break;
+       case IDD_WIZ97_OUTPUT:
+               topicPath = _T("/TestWizard_Output.html");
+               break;
+       case IDD_WIZ97_COMPLETION:
+               topicPath = _T("/TestWizard_Completion.html");
+               break;
+       }
+
+       TCHAR helpFileLink[2*MAX_PATH+1] = {0};
+       ::GetModuleFileName(NULL, helpFileLink, 2*MAX_PATH);
+       ::PathRenameExtension(helpFileLink, _T(".chm"));
+
+       UINT command = HH_DISPLAY_TOC;
+       if(topicPath)
+       {
+               command = HH_DISPLAY_TOPIC;
+               ::lstrcat(helpFileLink, _T("::"));
+               ::lstrcat(helpFileLink, topicPath);
+       }
+
+       // Add the window name
+       ::lstrcat(helpFileLink, _T(">$global_main"));
+
+       // In real code, you'd probably want the "main frame" to be hWndHelpParent.
+       HWND hWndHelpParent = ::GetActiveWindow();
+
+       HWND hWndHelp = ::HtmlHelp(hWndHelpParent, helpFileLink, command, NULL);
+       ATLASSERT(hWndHelp != NULL);
+
+       if(hWndHelp != NULL && topicPath != NULL)
+       {
+               // NOTE: It'd probably be better to use the notification
+               //  HHN_NAVCOMPLETE to know when we can synchronize
+               ::Sleep(200);
+               ::PostMessage(hWndHelp, WM_COMMAND, MAKEWPARAM(IDTB_SYNC, 0), 0);
+       }
+}
+
+void CTestWizardInfo::ShowContextHelp(LPHELPINFO helpInfo)
+{
+       TCHAR helpFileLink[2*MAX_PATH+1] = {0};
+       ::GetModuleFileName(NULL, helpFileLink, 2*MAX_PATH);
+       ::PathRenameExtension(helpFileLink, _T(".chm"));
+
+       ::lstrcat(helpFileLink, _T("::/Context.txt"));
+
+       DWORD idList[3] = { helpInfo->iCtrlId, (DWORD)helpInfo->dwContextId, 0};
+
+       // For more control on the appearance, we could use HH_DISPLAY_TEXT_POPUP
+       HWND hWndHelp = ::HtmlHelp((HWND)helpInfo->hItemHandle, helpFileLink, HH_TP_HELP_WM_HELP, (DWORD_PTR)idList);
+       ATLASSERT(hWndHelp != NULL);
+       if(hWndHelp == NULL)
+       {
+               ::MessageBox(::GetActiveWindow(), _T("Unable to show context help"), _T("Error"), MB_OK | MB_ICONERROR);
+       }
+}
+
+bool CTestWizardInfo::FinishWizard(HWND hWndParent)
+{
+       bool success = false;
+
+       switch(m_outputType)
+       {
+       case eOutput_SendEMail:
+               success = this->FinishWizard_SendEMail(hWndParent);
+               break;
+       case eOutput_SaveToFile:
+               success = this->FinishWizard_SaveToFile(hWndParent);
+               break;
+       case eOutput_Clipboard:
+       default:
+               success = this->FinishWizard_CopyToClipboard(hWndParent);
+               break;
+       }
+
+       return success;
+}
+
+bool CTestWizardInfo::FinishWizard_CopyToClipboard(HWND hWndParent)
+{
+       bool success = false;
+
+       CTestWizardFindFile_BuildString callback;
+       callback.SetTestWizardInfo(this);
+
+       this->FindFiles(&callback);
+
+       const CString& output = callback.GetOutputString();
+
+       size_t cbOutput = (output.GetLength() + 1) * sizeof(TCHAR);
+       HGLOBAL hClipboardData = ::GlobalAlloc((GMEM_MOVEABLE|GMEM_ZEROINIT), cbOutput);
+       if(hClipboardData != NULL)
+       {
+               LPVOID pClipboardData = ::GlobalLock(hClipboardData);
+               LPCTSTR sourceData = output.operator LPCTSTR();
+               ::CopyMemory(pClipboardData, sourceData, cbOutput);
+               ::GlobalUnlock(hClipboardData);
+
+               BOOL openedClipboard = ::OpenClipboard(hWndParent);
+               if(openedClipboard)
+               {
+                       ::EmptyClipboard();
+
+#ifdef _UNICODE
+                       HANDLE handle = ::SetClipboardData(CF_UNICODETEXT, hClipboardData);
+                       // Let the OS synthesize CF_TEXT
+#else
+                       HANDLE handle = ::SetClipboardData(CF_TEXT, hClipboardData);
+                       // Let the OS synthesize CF_UNICODETEXT
+#endif
+
+                       success = (handle != NULL);
+
+                       ::CloseClipboard();
+               }
+       }
+
+       if(!success)
+       {
+               ::MessageBox(hWndParent,
+                       _T("Failed to copy the file list to the clipboard"),
+                       _T("Error"), MB_OK | MB_ICONERROR);
+       }
+
+       return success;
+}
+
+bool CTestWizardInfo::FinishWizard_SendEMail(HWND hWndParent)
+{
+       bool success = false;
+
+       CTestWizardFindFile_BuildString callback;
+       callback.SetTestWizardInfo(this);
+
+       this->FindFiles(&callback);
+
+       const CString& output = callback.GetOutputString();
+
+       HMODULE hMapi = LoadLibrary(_T("MAPI32.DLL"));
+       if(hMapi)
+       {
+               LPMAPISENDMAIL pfnMAPISendMail = (LPMAPISENDMAIL) ::GetProcAddress(hMapi, "MAPISendMail");
+               if(pfnMAPISendMail)
+               {
+                       USES_CONVERSION;
+                       MapiMessage message = {0};
+                       message.lpszNoteText = (LPSTR)T2CA(output);
+
+                       ULONG result = pfnMAPISendMail(NULL, NULL, &message, MAPI_DIALOG, 0);
+                       success = (result == SUCCESS_SUCCESS) || (result == MAPI_USER_ABORT);
+               }
+               
+               ::FreeLibrary(hMapi);
+               hMapi = NULL;
+       }
+
+       if(!success)
+       {
+               ::MessageBox(hWndParent,
+                       _T("Failed to send the file list via e-mail"),
+                       _T("Error"), MB_OK | MB_ICONERROR);
+       }
+
+       return success;
+}
+
+bool CTestWizardInfo::FinishWizard_SaveToFile(HWND hWndParent)
+{
+       CTestWizardFindFile_SaveToFile callback;
+       callback.SetTestWizardInfo(this);
+
+       this->FindFiles(&callback);
+
+       bool success = callback.Succeeded();
+
+       if(!success)
+       {
+               CString failureReason = callback.GetFailureReason();
+               if(failureReason.GetLength() < 1)
+               {
+                       failureReason.Format(
+                               _T("Failed to save the file list to the file\r\n%s"),
+                               m_outputFileName);
+               }
+
+               ::MessageBox(hWndParent,
+                       failureReason,
+                       _T("Error"), MB_OK | MB_ICONERROR);
+       }
+
+       return success;
+}
+
+void CTestWizardFindFile_BuildString::OnFileFound(LPCTSTR directory, LPWIN32_FIND_DATA findFileData)
+{
+       TCHAR fullFilePath[MAX_PATH+3] = {0};
+       ::PathCombine(fullFilePath, directory, findFileData->cFileName);
+       ::lstrcat(fullFilePath, _T("\r\n"));
+
+       m_output += fullFilePath;
+}
+
+bool CTestWizardFindFile_SaveToFile::OnBeginFindFiles(void)
+{
+       m_outputFileName = m_pTestWizardInfo->GetOutputFileName();
+       m_outputFileEncoding = m_pTestWizardInfo->GetOutputFileEncoding();
+
+       m_hFile = ::CreateFile(
+               m_outputFileName, GENERIC_WRITE, 0, NULL,
+               CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+       if(m_hFile == INVALID_HANDLE_VALUE)
+       {
+               m_succeeded = false;
+
+               m_failureReason.Format(
+                       _T("Unable to open the file '%s' for writing."),
+                       m_outputFileName);
+       }
+       else
+       {
+               m_succeeded = true;
+
+               switch(m_outputFileEncoding)
+               {
+               case eEncoding_UCS2:
+                       {
+                               // Write out UCS-2 byte order mark (BOM)
+                               // 0xFEFF
+                               BYTE bom[2] = {0xFF, 0xFE};
+                               DWORD cbWritten = 0;
+                               ::WriteFile(m_hFile, bom, 2, &cbWritten, NULL);
+                       }
+                       break;
+               case eEncoding_UTF8:
+                       {
+                               // Write out UTF-8 byte order mark (BOM)
+                               BYTE bom[3] = {0xEF, 0xBB, 0xBF};
+                               DWORD cbWritten = 0;
+                               ::WriteFile(m_hFile, bom, 3, &cbWritten, NULL);
+                       }
+                       break;
+               }
+       }
+
+       return m_succeeded;
+}
+
+void CTestWizardFindFile_SaveToFile::OnEndFindFiles(void)
+{
+       if(m_hFile != INVALID_HANDLE_VALUE)
+       {
+               ::CloseHandle(m_hFile);
+               m_hFile = INVALID_HANDLE_VALUE;
+       }
+}
+
+void CTestWizardFindFile_SaveToFile::OnFileFound(LPCTSTR directory, LPWIN32_FIND_DATA findFileData)
+{
+       if(m_hFile != INVALID_HANDLE_VALUE)
+       {
+               LPCTSTR fileSpec = findFileData->cFileName;
+               DWORD cbWritten = 0;
+
+               switch(m_outputFileEncoding)
+               {
+               case eEncoding_ASCII:
+                       {
+                               USES_CONVERSION;
+                               LPCSTR directoryA = T2CA(directory);
+                               LPCSTR fileSpecA = T2CA(fileSpec);
+
+                               ::WriteFile(m_hFile, directoryA, ::lstrlenA(directoryA)*sizeof(CHAR), &cbWritten, NULL);
+                               ::WriteFile(m_hFile, "\\", 1*sizeof(CHAR), &cbWritten, NULL);
+                               ::WriteFile(m_hFile, fileSpecA, ::lstrlenA(fileSpecA)*sizeof(CHAR), &cbWritten, NULL);
+                               ::WriteFile(m_hFile, "\r\n", 2*sizeof(CHAR), &cbWritten, NULL);
+                       }
+                       break;
+               case eEncoding_UCS2:
+                       {
+                               USES_CONVERSION;
+                               LPCWSTR directoryW = T2CW(directory);
+                               LPCWSTR fileSpecW = T2CW(fileSpec);
+
+                               ::WriteFile(m_hFile, directoryW, ::lstrlenW(directoryW)*sizeof(WCHAR), &cbWritten, NULL);
+                               ::WriteFile(m_hFile, "\\", 1*sizeof(WCHAR), &cbWritten, NULL);
+                               ::WriteFile(m_hFile, fileSpecW, ::lstrlenW(fileSpecW)*sizeof(WCHAR), &cbWritten, NULL);
+                               ::WriteFile(m_hFile, L"\r\n", 2*sizeof(WCHAR), &cbWritten, NULL);
+                       }
+                       break;
+               case eEncoding_UTF8:
+                       {
+                               // NOTE: To preserve unicode characters, use the unicode build.
+                               //  Otherwise we've already "lost precision" by now with the ANSI/ASCII build
+                               //  and FindFirstFile(A)/FindNextFile(A).
+
+                               USES_CONVERSION;
+                               LPCWSTR directoryW = T2CW(directory);
+                               LPCWSTR fileSpecW = T2CW(fileSpec);
+
+                               // Directory
+                               int cchDirectoryW = ::lstrlenW(directoryW);
+                               int cbDirectoryMB = ::WideCharToMultiByte(CP_UTF8, 0, directoryW, cchDirectoryW, NULL, 0, NULL, NULL );
+                               LPSTR directoryMB = new CHAR[cbDirectoryMB];
+                               if(directoryMB)
+                               {
+                                       ::WideCharToMultiByte(CP_UTF8, 0, directoryW, cchDirectoryW, directoryMB, cbDirectoryMB, NULL, NULL );
+                                       ::WriteFile(m_hFile, directoryMB, cbDirectoryMB, &cbWritten, NULL );
+                                       delete [] directoryMB;
+                                       directoryMB = NULL;
+                               }
+
+                               // Separator
+                               ::WriteFile(m_hFile, "\\", 1*sizeof(CHAR), &cbWritten, NULL);
+
+                               // FileSpec
+                               int cchFileSpecW = ::lstrlenW(fileSpecW);
+                               int cbFileSpecMB = ::WideCharToMultiByte(CP_UTF8, 0, fileSpecW, cchFileSpecW, NULL, 0, NULL, NULL );
+                               LPSTR fileSpecMB = new CHAR[cbFileSpecMB];
+                               if(fileSpecMB)
+                               {
+                                       ::WideCharToMultiByte(CP_UTF8, 0, fileSpecW, cchFileSpecW, fileSpecMB, cbFileSpecMB, NULL, NULL );
+                                       ::WriteFile(m_hFile, fileSpecMB, cbFileSpecMB, &cbWritten, NULL );
+                                       delete [] fileSpecMB;
+                                       fileSpecMB = NULL;
+                               }
+
+                               // Newline
+                               ::WriteFile(m_hFile, "\r\n", 2*sizeof(CHAR), &cbWritten, NULL);
+                       }
+                       break;
+               }
+       }
+}
+
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardInfo.h b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardInfo.h
new file mode 100644 (file)
index 0000000..ab921c7
--- /dev/null
@@ -0,0 +1,219 @@
+
+#ifndef __TestWizardInfo_h__
+#define __TestWizardInfo_h__
+
+static LPCTSTR s_allFiles = _T("*.*");
+
+class ITestWizardFindFileCB
+{
+public:
+       virtual bool OnBeginFindFiles(void) = 0;
+       virtual void OnEndFindFiles(void) = 0;
+       virtual bool OnBeginDirectorySearch(LPCTSTR directory) = 0;
+       virtual void OnEndDirectorySearch(LPCTSTR directory) = 0;
+
+       virtual void OnFileFound(LPCTSTR directory, LPWIN32_FIND_DATA findFileData) = 0;
+};
+
+// Enumerations
+enum TestWizardOutputType
+{
+       eOutput_Clipboard  = 0,
+       eOutput_SendEMail  = 1,
+       eOutput_SaveToFile = 2,
+
+       eOutput_First      = eOutput_Clipboard,
+       eOutput_Last       = eOutput_SaveToFile,
+};
+enum TestWizardOutputFileEncoding
+{
+       eEncoding_ASCII = 0,
+       eEncoding_UCS2  = 1,
+       eEncoding_UTF8  = 2,
+
+       eEncoding_First = eEncoding_ASCII,
+       eEncoding_Last  = eEncoding_UTF8,
+};
+enum TestWizardQuerySiblingNotifiations
+{
+       eQuerySibling_ParametersFileChanged = 0,
+};
+
+class CTestWizardInfo
+{
+protected:
+// Typedefs
+       typedef CTestWizardInfo thisClass;
+
+// Member variables
+       CString m_path, m_filter;
+       bool m_showWelcome, m_recurse;
+
+       TestWizardOutputType m_outputType;
+       CString m_outputFileName;
+       TestWizardOutputFileEncoding m_outputFileEncoding;
+
+public:
+// Constructor/Destructor
+       CTestWizardInfo();
+       virtual ~CTestWizardInfo();
+
+// General methods
+       // Set
+       bool SetShowWelcome(bool showWelcome);
+       bool SetPath(LPCTSTR path);
+       bool SetRecurse(bool recurse);
+       bool SetFilter(LPCTSTR filter);
+       bool SetOutputType(TestWizardOutputType outputType);
+       bool SetOutputTypeByDisplayName(LPCTSTR typeDisplayName);
+       bool SetOutputFileName(LPCTSTR outputFileName);
+       bool SetOutputFileEncoding(TestWizardOutputFileEncoding outputFileEncoding);
+       bool SetOutputFileEncodingByDisplayName(LPCTSTR encodingDisplayName);
+
+       // Get
+       bool GetShowWelcome(void) const;
+       CString GetPath(void) const;
+       bool GetRecurse(void) const;
+       CString GetFilter(void) const;
+       TestWizardOutputType GetOutputType(void) const;
+       CString GetOutputTypeDisplayName(void) const;
+       CString GetOutputFileName(void) const;
+       TestWizardOutputFileEncoding GetOutputFileEncoding(void) const;
+       CString GetOutputFileEncodingDisplayName(void) const;
+
+       // Static methods
+       static bool IsValidOutputType(DWORD outputType);
+       static bool IsValidOutputFileEncoding(DWORD outputFileEncoding);
+       static CString GetOutputTypeDisplayName(TestWizardOutputType outputType);
+       static CString GetOutputFileEncodingDisplayName(TestWizardOutputFileEncoding outputFileEncoding);
+       static bool GetOutputTypeForDisplayName(LPCTSTR typeDisplayName, TestWizardOutputType& outputType);
+       static bool GetOutputFileEncodingForDisplayName(LPCTSTR encodingDisplayName, TestWizardOutputFileEncoding& outputFileEncoding);
+
+       // File List
+       int FindFiles(ITestWizardFindFileCB* callback) const;
+
+       // Page Navigation
+       int FindPreviousPage(int pageDialogId) const;
+       int FindNextPage(int pageDialogId) const;
+
+       // Help
+       void ShowHelp(int pageDialogId, int controlId = 0);
+       void ShowContextHelp(LPHELPINFO helpInfo);
+
+       // FinishWizard
+       bool FinishWizard(HWND hWndParent);
+
+protected:
+// Implementation methods
+
+       int FindFiles(ITestWizardFindFileCB* callback, LPCTSTR directory, LPCTSTR filter, bool recurse) const;
+       bool FinishWizard_CopyToClipboard(HWND hWndParent);
+       bool FinishWizard_SendEMail(HWND hWndParent);
+       bool FinishWizard_SaveToFile(HWND hWndParent);
+};
+
+class CTestWizardInfoRef
+{
+protected:
+// Data members
+       CTestWizardInfo* m_pTestWizardInfo;
+
+public:
+// Constructors
+       CTestWizardInfoRef(CTestWizardInfo* pTestWizardInfo = NULL) : 
+               m_pTestWizardInfo(pTestWizardInfo)
+       {
+       }
+
+// Public methods
+       CTestWizardInfo* GetTestWizardInfo(void)
+       {
+               return m_pTestWizardInfo;
+       }
+       void SetTestWizardInfo(CTestWizardInfo* pTestWizardInfo)
+       {
+               m_pTestWizardInfo = pTestWizardInfo;
+       }
+
+};
+
+class CTestWizardFindFile_BuildString :
+       public CTestWizardInfoRef,
+       public ITestWizardFindFileCB
+{
+protected:
+// Typedefs
+       typedef CTestWizardInfoRef baseClass;
+
+// Data members
+       CString m_output;
+
+public:
+// ITestWizardFindFileCB
+       virtual bool OnBeginFindFiles(void) { return true; }
+       virtual void OnEndFindFiles(void) { }
+       virtual bool OnBeginDirectorySearch(LPCTSTR /*directory*/) { return true; }
+       virtual void OnEndDirectorySearch(LPCTSTR /*directory*/) { }
+
+       virtual void OnFileFound(LPCTSTR directory, LPWIN32_FIND_DATA findFileData);
+
+// Public methods
+       const CString& GetOutputString() const
+       {
+               return m_output;
+       }
+};
+
+class CTestWizardFindFile_SaveToFile :
+       public CTestWizardInfoRef,
+       public ITestWizardFindFileCB
+{
+protected:
+// Typedefs
+       typedef CTestWizardInfoRef baseClass;
+
+// Data members
+       CString m_outputFileName;
+       HANDLE m_hFile;
+       TestWizardOutputFileEncoding m_outputFileEncoding;
+       bool m_succeeded;
+       CString m_failureReason;
+
+public:
+// Constructor/Destructor
+       CTestWizardFindFile_SaveToFile() :
+               m_hFile(INVALID_HANDLE_VALUE),
+               m_outputFileEncoding(eEncoding_ASCII),
+               m_succeeded(false)
+       {
+       }
+
+       ~CTestWizardFindFile_SaveToFile()
+       {
+               if(m_hFile != INVALID_HANDLE_VALUE)
+               {
+                       ::CloseHandle(m_hFile);
+                       m_hFile = INVALID_HANDLE_VALUE;
+               }
+       }
+
+// ITestWizardFindFileCB
+       virtual bool OnBeginFindFiles(void);
+       virtual void OnEndFindFiles(void);
+       virtual bool OnBeginDirectorySearch(LPCTSTR /*directory*/) { return true; }
+       virtual void OnEndDirectorySearch(LPCTSTR /*directory*/) { }
+
+       virtual void OnFileFound(LPCTSTR directory, LPWIN32_FIND_DATA findFileData);
+
+// Public methods
+       bool Succeeded(void) const
+       {
+               return m_succeeded;
+       }
+       CString GetFailureReason(void) const
+       {
+               return m_failureReason;
+       }
+};
+
+#endif // __TestWizardInfo_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardOutputPage.cpp b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardOutputPage.cpp
new file mode 100644 (file)
index 0000000..a58e302
--- /dev/null
@@ -0,0 +1,227 @@
+
+#include "stdafx.h"
+#include "TestWizardOutputPage.h"
+
+LRESULT CTestWizardOutputPage::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CWaitCursor waitCursor;
+
+       this->InitializeControls();
+       this->InitializeValues();
+
+       return 1;
+}
+
+LRESULT CTestWizardOutputPage::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+       // Be sure the base gets the message too
+       bHandled = FALSE;
+
+       this->UninitializeControls();   
+       return 0;
+}
+
+LRESULT CTestWizardOutputPage::OnClickCopyToClipboard(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       m_labelSaveFileName.EnableWindow(FALSE);
+       m_editFileName.EnableWindow(FALSE);
+       m_buttonBrowseFile.EnableWindow(FALSE);
+       m_labelFileEncoding.EnableWindow(FALSE);
+       m_comboFileEncoding.EnableWindow(FALSE);
+       return 0;
+}
+
+LRESULT CTestWizardOutputPage::OnClickSendEmail(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       m_labelSaveFileName.EnableWindow(FALSE);
+       m_editFileName.EnableWindow(FALSE);
+       m_buttonBrowseFile.EnableWindow(FALSE);
+       m_labelFileEncoding.EnableWindow(FALSE);
+       m_comboFileEncoding.EnableWindow(FALSE);
+       return 0;
+}
+
+LRESULT CTestWizardOutputPage::OnClickSaveToFile(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       m_labelSaveFileName.EnableWindow(TRUE);
+       m_editFileName.EnableWindow(TRUE);
+       m_buttonBrowseFile.EnableWindow(TRUE);
+       m_labelFileEncoding.EnableWindow(TRUE);
+       m_comboFileEncoding.EnableWindow(TRUE);
+       return 0;
+}
+
+LRESULT CTestWizardOutputPage::OnClickBrowseFileName(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CFileDialog dialog(FALSE,
+               _T("txt"), NULL,
+               OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ENABLESIZING | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST,
+               _T("Text Documents (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"), m_hWnd);
+       dialog.m_ofn.lpstrTitle = _T("Select where to output the file list");
+
+       CString initialDirectory = m_pTestWizardInfo->GetPath();
+
+       CString fileName;
+       int cchFileName = m_editFileName.GetWindowTextLength();
+       m_editFileName.GetWindowText(fileName.GetBuffer(cchFileName + 1), cchFileName + 1);
+       fileName.ReleaseBuffer(cchFileName);
+       fileName.TrimLeft();
+       fileName.TrimRight();
+
+       if(fileName.GetLength() > 0)
+       {
+               initialDirectory = fileName;
+               ::PathRemoveFileSpec(initialDirectory.GetBuffer(0));
+               initialDirectory.ReleaseBuffer();
+       }
+
+       if((initialDirectory.GetLength() > 0) && (::GetFileAttributes(initialDirectory) != INVALID_FILE_ATTRIBUTES))
+       {
+               dialog.m_ofn.lpstrInitialDir = initialDirectory;
+       }
+
+       INT_PTR dialogResult = dialog.DoModal();
+       if(IDOK == dialogResult)
+       {
+               m_editFileName.SetWindowText(dialog.m_szFileName);
+       }
+
+       return 0;
+}
+
+void CTestWizardOutputPage::InitializeControls(void)
+{
+       m_radioCopyToClipboard = this->GetDlgItem(IDC_RADIO_COPYTOCLIPBOARD);
+       m_radioSendEmail = this->GetDlgItem(IDC_RADIO_SENDEMAIL);
+       m_radioSaveToFile = this->GetDlgItem(IDC_RADIO_SAVETOFILE);
+
+       m_labelSaveFileName = this->GetDlgItem(IDC_LABEL_FILENAME);
+       m_editFileName = this->GetDlgItem(IDC_EDIT_SAVETOFILE);
+       m_buttonBrowseFile = this->GetDlgItem(IDC_BTN_FILEBROWSE);
+       m_labelFileEncoding = this->GetDlgItem(IDC_LABEL_FILEENCODING);
+       m_comboFileEncoding = this->GetDlgItem(IDC_COMBO_FILEENCODING);
+
+       for(int i=(int)eEncoding_First; i<=(int)eEncoding_Last; ++i)
+       {
+               m_comboFileEncoding.AddString(
+                       CTestWizardInfo::GetOutputFileEncodingDisplayName((TestWizardOutputFileEncoding)i));
+       }
+
+       m_comboFileEncoding.SetCurSel(0);
+
+       // It's possible to have more control over the auto-complete functionality.
+       // See MSDN for info about IAutoComplete2, IACList2, and so on.
+       ::SHAutoComplete(m_editFileName, SHACF_FILESYSTEM | SHACF_AUTOAPPEND_FORCE_ON | SHACF_AUTOSUGGEST_FORCE_ON);
+}
+
+void CTestWizardOutputPage::UninitializeControls(void)
+{
+}
+
+void CTestWizardOutputPage::InitializeValues(void)
+{
+       // We'll initialize outputFileName and outputFileEncoding even if
+       // the output type is not eOutput_SaveToFile (so that if a previous
+       // run had store something, those will be the defaults if they want
+       // to switch back to eOutput_SaveToFile).
+       CString outputFileName = m_pTestWizardInfo->GetOutputFileName();
+       TestWizardOutputFileEncoding outputFileEncoding = m_pTestWizardInfo->GetOutputFileEncoding();
+
+       m_editFileName.SetWindowText(outputFileName);
+       m_comboFileEncoding.SetCurSel((int)outputFileEncoding);
+
+       TestWizardOutputType outputType = m_pTestWizardInfo->GetOutputType();
+
+       switch(outputType)
+       {
+       case eOutput_SendEMail:
+               m_radioSendEmail.Click();
+               break;
+       case eOutput_SaveToFile:
+               m_radioSaveToFile.Click();
+               break;
+       case eOutput_Clipboard:
+       default:
+               m_radioCopyToClipboard.Click();
+               break;
+       }
+}
+
+bool CTestWizardOutputPage::StoreValues(void)
+{
+       if(m_radioCopyToClipboard.GetCheck() == BST_CHECKED)
+       {
+               m_pTestWizardInfo->SetOutputType(eOutput_Clipboard);
+       }
+       else if(m_radioSendEmail.GetCheck() == BST_CHECKED)
+       {
+               m_pTestWizardInfo->SetOutputType(eOutput_SendEMail);
+       }
+       else if(m_radioSaveToFile.GetCheck() == BST_CHECKED)
+       {
+               m_pTestWizardInfo->SetOutputType(eOutput_SaveToFile);
+
+               CString fileName;
+               int cchFileName = m_editFileName.GetWindowTextLength();
+               m_editFileName.GetWindowText(fileName.GetBuffer(cchFileName + 1), cchFileName + 1);
+               fileName.ReleaseBuffer(cchFileName);
+               fileName.TrimLeft();
+               fileName.TrimRight();
+
+               if(fileName.GetLength() < 1)
+               {
+                       this->MessageBox(
+                               _T("Please provide a file name to save the list of files."),
+                               _T("No File Name"), MB_OK | MB_ICONWARNING);
+                       m_editFileName.SetFocus();
+                       return false;
+               }
+               else
+               {
+                       m_pTestWizardInfo->SetOutputFileName(fileName);
+               }
+
+               m_pTestWizardInfo->SetOutputFileEncoding(
+                       (TestWizardOutputFileEncoding) m_comboFileEncoding.GetCurSel());
+       }
+
+       return true;
+}
+
+// Overrides from base class
+int CTestWizardOutputPage::OnSetActive()
+{
+       this->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
+
+       // 0 = allow activate
+       // -1 = go back to page that was active
+       // page ID = jump to page
+       return 0;
+}
+
+int CTestWizardOutputPage::OnWizardNext()
+{
+       bool success = this->StoreValues();
+       if(!success)
+       {
+               // Any errors are already reported, and if appropriate,
+               // the control that needs attention has been given focus.
+               return -1;
+       }
+
+       // 0  = goto next page
+       // -1 = prevent page change
+       // >0 = jump to page by dlg ID
+
+       return m_pTestWizardInfo->FindNextPage(IDD);
+}
+
+int CTestWizardOutputPage::OnWizardBack()
+{
+       return m_pTestWizardInfo->FindPreviousPage(IDD);
+}
+
+void CTestWizardOutputPage::OnHelp()
+{
+       m_pTestWizardInfo->ShowHelp(IDD);
+}
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardOutputPage.h b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardOutputPage.h
new file mode 100644 (file)
index 0000000..b3bbfea
--- /dev/null
@@ -0,0 +1,72 @@
+
+#ifndef __TestWizardOutputPage_h__
+#define __TestWizardOutputPage_h__
+
+#include "TestWizardInfo.h"
+
+class CTestWizardOutputPage :
+       public CWizard97InteriorPageImpl<CTestWizardOutputPage>,
+       public CTestWizardInfoRef
+{
+protected:
+// Typedefs
+       typedef CTestWizardOutputPage thisClass;
+       typedef CWizard97InteriorPageImpl<CTestWizardOutputPage> baseClass;
+
+// Data members
+       CButton m_radioCopyToClipboard;
+       CButton m_radioSendEmail;
+       CButton m_radioSaveToFile;
+
+       CStatic m_labelSaveFileName;
+       CEdit   m_editFileName;
+       CButton m_buttonBrowseFile;
+       CStatic m_labelFileEncoding;
+       CComboBox m_comboFileEncoding;
+
+public:
+// Constructor
+       CTestWizardOutputPage(_U_STRINGorID title = (LPCTSTR)NULL) :
+               baseClass(title)
+       {
+               baseClass::SetHeaderTitle(_T("Output File List"));
+               baseClass::SetHeaderSubTitle(_T("Please choose how to output the file list."));
+       }
+
+// Message Handlers
+       enum { IDD = IDD_WIZ97_OUTPUT };
+       BEGIN_MSG_MAP(thisClass)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+
+               COMMAND_HANDLER(IDC_RADIO_COPYTOCLIPBOARD, BN_CLICKED, OnClickCopyToClipboard)
+               COMMAND_HANDLER(IDC_RADIO_SENDEMAIL, BN_CLICKED, OnClickSendEmail)
+               COMMAND_HANDLER(IDC_RADIO_SAVETOFILE, BN_CLICKED, OnClickSaveToFile)
+               COMMAND_HANDLER(IDC_BTN_FILEBROWSE, BN_CLICKED, OnClickBrowseFileName)
+
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+       LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+       LRESULT OnClickCopyToClipboard(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+       LRESULT OnClickSendEmail(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+       LRESULT OnClickSaveToFile(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+       LRESULT OnClickBrowseFileName(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+
+// Helpers
+       void InitializeControls(void);
+       void UninitializeControls(void);
+       void InitializeValues(void);
+       bool StoreValues(void);
+
+// Overrides from base class
+       int OnSetActive();
+       int OnWizardNext();
+       int OnWizardBack();
+       void OnHelp();
+
+};
+
+#endif // __TestWizardOutputPage_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardPathFilterPage.cpp b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardPathFilterPage.cpp
new file mode 100644 (file)
index 0000000..3a5b4f7
--- /dev/null
@@ -0,0 +1,217 @@
+
+#include "stdafx.h"
+#include "TestWizardPathFilterPage.h"
+
+#include "FolderDialogStatusText.h"
+
+LRESULT CTestWizardPathFilterPage::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       CWaitCursor waitCursor;
+
+       this->InitializeControls();
+       this->InitializeValues();
+
+       return 1;
+}
+
+LRESULT CTestWizardPathFilterPage::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
+{
+       // Be sure the base gets the message too
+       bHandled = FALSE;
+
+       this->UninitializeControls();   
+       return 0;
+}
+
+LRESULT CTestWizardPathFilterPage::OnClickFilterAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       m_editFilterCustom.SetReadOnly(TRUE);
+       return 0;
+}
+
+LRESULT CTestWizardPathFilterPage::OnClickFilterCustom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       m_editFilterCustom.SetReadOnly(FALSE);
+       return 0;
+}
+
+LRESULT CTestWizardPathFilterPage::OnClickBrowsePath(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+       CFolderDialogStatusText dialog(
+               m_hWnd, _T("Root directory:"),
+               (/*BIF_EDITBOX |*/ BIF_NEWDIALOGSTYLE | BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT));
+
+       CString path;
+       int cchPath = m_editPath.GetWindowTextLength();
+       m_editPath.GetWindowText(path.GetBuffer(cchPath + 1), cchPath + 1);
+       path.ReleaseBuffer(cchPath);
+
+       if(path.GetLength() > 0)
+       {
+               dialog.SetInitialFolder(path);
+       }
+
+       if(IDOK == dialog.DoModal())
+       {
+               m_editPath.SetWindowText(dialog.GetFolderPath());
+       }
+
+       return 0;
+}
+
+void CTestWizardPathFilterPage::InitializeControls(void)
+{
+       m_labelPath = this->GetDlgItem(IDC_LABEL_PATH);
+       m_editPath = this->GetDlgItem(IDC_EDIT_PATH);
+       m_buttonBrowsePath = this->GetDlgItem(IDC_BTN_BROWSEPATH);
+
+       m_radioRecurse = this->GetDlgItem(IDC_RADIO_RECURSE);
+       m_radioNoRecurse = this->GetDlgItem(IDC_RADIO_NORECURSE);
+
+       m_labelFilter = this->GetDlgItem(IDC_LABEL_FILTER);
+       m_radioFilterAll = this->GetDlgItem(IDC_RADIO_FILTER_ALL);
+       m_radioFilterCustom = this->GetDlgItem(IDC_RADIO_FILTER_CUSTOM);
+       m_editFilterCustom = this->GetDlgItem(IDC_EDIT_FILTER);
+
+       m_editFilterCustom.SetReadOnly(TRUE);
+}
+
+void CTestWizardPathFilterPage::UninitializeControls(void)
+{
+
+}
+
+void CTestWizardPathFilterPage::InitializeValues(void)
+{
+       CString path = m_pTestWizardInfo->GetPath();
+       CString filter = m_pTestWizardInfo->GetFilter();
+       bool recurse = m_pTestWizardInfo->GetRecurse();
+
+       m_editPath.SetWindowText(path);
+
+       if(recurse)
+       {
+               m_radioRecurse.Click();
+       }
+       else
+       {
+               m_radioNoRecurse.Click();
+       }
+
+       if(filter == s_allFiles)
+       {
+               m_radioFilterAll.Click();
+               m_editFilterCustom.SetWindowText(s_allFiles);
+       }
+       else
+       {
+               m_radioFilterCustom.Click();
+               m_editFilterCustom.SetWindowText(filter);
+       }
+}
+
+bool CTestWizardPathFilterPage::StoreValues(void)
+{
+       CString path;
+       int cchPath = m_editPath.GetWindowTextLength();
+       m_editPath.GetWindowText(path.GetBuffer(cchPath + 1), cchPath + 1);
+       path.ReleaseBuffer(cchPath);
+       path.TrimLeft();
+       path.TrimRight();
+
+       if(path.GetLength() < 1)
+       {
+               this->MessageBox(
+                       _T("Please provide a location to find files."),
+                       _T("No path"), MB_OK | MB_ICONWARNING);
+               m_editPath.SetFocus();
+               return false;
+       }
+       else
+       {
+               m_pTestWizardInfo->SetPath(path);
+       }
+
+       bool recurse = (m_radioRecurse.GetCheck() == BST_CHECKED);
+       m_pTestWizardInfo->SetRecurse(recurse);
+
+       if(m_radioFilterAll.GetCheck() == BST_CHECKED)
+       {
+               m_pTestWizardInfo->SetFilter(s_allFiles);
+       }
+       else
+       {
+               CString filter;
+               int cchFilter = m_editFilterCustom.GetWindowTextLength();
+               m_editFilterCustom.GetWindowText(filter.GetBuffer(cchFilter + 1), cchFilter + 1);
+               filter.ReleaseBuffer(cchFilter);
+               filter.TrimLeft();
+               filter.TrimRight();
+
+               if(filter.GetLength() < 1)
+               {
+                       m_radioFilterAll.Click();
+                       m_editFilterCustom.SetWindowText(s_allFiles);
+
+                       m_pTestWizardInfo->SetFilter(s_allFiles);
+               }
+               else
+               {
+                       m_pTestWizardInfo->SetFilter(filter);
+               }
+       }
+
+       return true;
+}
+
+// Overrides from base class
+int CTestWizardPathFilterPage::OnSetActive()
+{
+       this->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
+
+       // 0 = allow activate
+       // -1 = go back to page that was active
+       // page ID = jump to page
+       return 0;
+}
+
+int CTestWizardPathFilterPage::OnWizardNext()
+{
+       bool success = this->StoreValues();
+       if(!success)
+       {
+               // Any errors are already reported, and if appropriate,
+               // the control that needs attention has been given focus.
+               return -1;
+       }
+
+       // 0  = goto next page
+       // -1 = prevent page change
+       // >0 = jump to page by dlg ID
+
+       return m_pTestWizardInfo->FindNextPage(IDD);
+}
+
+int CTestWizardPathFilterPage::OnWizardBack()
+{
+       return m_pTestWizardInfo->FindPreviousPage(IDD);
+}
+
+void CTestWizardPathFilterPage::OnHelp()
+{
+       // NOTE: Several controls on this dialog have been given
+       //  context sensitive help descriptions, and the HtmlHelp
+       //  file is setup to recognize their help IDs.  Please
+       //  look at resource.hm, help\Context.h, help\Context.txt
+       //  and the help project Wizard97Test.hhp.
+       //
+       // It's also important to note that context help doesn't
+       //  come through this route, but rather goes to the page and
+       //  then the sheet (if not handled) as WM_HELP with dwContextId
+       //  in the HELPINFO structure set to a non-zero value.
+       //  See the sheet for how it deals with context help.
+       //  We get to this point if the user clicks on the help button
+       //  at the bottom.
+
+       m_pTestWizardInfo->ShowHelp(IDD);
+}
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardPathFilterPage.h b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardPathFilterPage.h
new file mode 100644 (file)
index 0000000..83c87ef
--- /dev/null
@@ -0,0 +1,72 @@
+
+#ifndef __TestWizardPathFilterPage_h__
+#define __TestWizardPathFilterPage_h__
+
+#include "TestWizardInfo.h"
+
+class CTestWizardPathFilterPage :
+       public CWizard97InteriorPageImpl<CTestWizardPathFilterPage>,
+       public CTestWizardInfoRef
+{
+protected:
+// Typedefs
+       typedef CTestWizardPathFilterPage thisClass;
+       typedef CWizard97InteriorPageImpl<CTestWizardPathFilterPage> baseClass;
+
+// Data members
+       CStatic m_labelPath;
+       CEdit m_editPath;
+       CButton m_buttonBrowsePath;
+
+       CButton m_radioRecurse;
+       CButton m_radioNoRecurse;
+
+       CStatic m_labelFilter;
+       CButton m_radioFilterAll;
+       CButton m_radioFilterCustom;
+       CEdit   m_editFilterCustom;
+
+public:
+// Constructor
+       CTestWizardPathFilterPage(_U_STRINGorID title = (LPCTSTR)NULL) :
+               baseClass(title)
+       {
+               baseClass::SetHeaderTitle(_T("Path and Filter to Find Files"));
+               baseClass::SetHeaderSubTitle(_T("Select the path and filter identifying a list of files."));
+       }
+
+// Message Handlers
+       enum { IDD = IDD_WIZ97_PATHFILTER };
+       BEGIN_MSG_MAP(thisClass)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+               MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+
+               COMMAND_HANDLER(IDC_RADIO_FILTER_ALL, BN_CLICKED, OnClickFilterAll)
+               COMMAND_HANDLER(IDC_RADIO_FILTER_CUSTOM, BN_CLICKED, OnClickFilterCustom)
+               COMMAND_HANDLER(IDC_BTN_BROWSEPATH, BN_CLICKED, OnClickBrowsePath)
+
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+       LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+       LRESULT OnClickFilterAll(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+       LRESULT OnClickFilterCustom(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+       LRESULT OnClickBrowsePath(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+       LRESULT OnClickBrowseDefaultPath(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+
+// Helpers
+       void InitializeControls(void);
+       void UninitializeControls(void);
+       void InitializeValues(void);
+       bool StoreValues(void);
+
+// Overrides from base class
+       int OnSetActive();
+       int OnWizardNext();
+       int OnWizardBack();
+       void OnHelp();
+};
+
+#endif // __TestWizardPathFilterPage_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardSheet.cpp b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardSheet.cpp
new file mode 100644 (file)
index 0000000..beb3d0b
--- /dev/null
@@ -0,0 +1,54 @@
+
+#include "stdafx.h"
+#include "TestWizardSheet.h"
+
+CTestWizardSheet::CTestWizardSheet(CTestWizardInfo* pTestWizardInfo, UINT uStartPage, HWND hWndParent) :
+       baseClass(_T("Test Wizard"), IDB_WIZ97_HEADER, IDB_WIZ97_WATERMARK, uStartPage, hWndParent),
+       infoRefClass(pTestWizardInfo)
+{
+       m_pageWelcome.SetTestWizardInfo(pTestWizardInfo);
+       m_pagePathFiler.SetTestWizardInfo(pTestWizardInfo);
+       m_pageFilePreview.SetTestWizardInfo(pTestWizardInfo);
+       m_pageOutput.SetTestWizardInfo(pTestWizardInfo);
+       m_pageCompletion.SetTestWizardInfo(pTestWizardInfo);
+
+       this->AddPage(m_pageWelcome);
+       this->AddPage(m_pagePathFiler);
+       this->AddPage(m_pageFilePreview);
+       this->AddPage(m_pageOutput);
+       this->AddPage(m_pageCompletion);
+}
+
+LRESULT CTestWizardSheet::OnHelp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
+{
+       // We get here when the user hits F1 while on a page,
+       // or uses the "What's This" button then clicks on a control.
+       // We can also handle WM_HELP on the page for the cases
+       // when a control on the dialog has focus.  If the page doesn't handle WM_HELP,
+       // then the sheet is given a chance to handle it (and we end up here).
+
+       LPHELPINFO helpInfo = (LPHELPINFO)lParam;
+       if(helpInfo)
+       {
+               if(helpInfo->dwContextId != 0)
+               {
+                       // If dwContextId is set, then the control with
+                       // focus has a help context ID, so we'll show context help.
+                       m_pTestWizardInfo->ShowContextHelp(helpInfo);
+               }
+               else
+               {
+                       int currentIndex = this->GetActiveIndex();
+                       if(currentIndex >= 0)
+                       {
+                               int pageDialogId = this->IndexToId(currentIndex);
+                               if(pageDialogId != 0)
+                               {
+                                       m_pTestWizardInfo->ShowHelp(pageDialogId, helpInfo->iCtrlId);
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardSheet.h b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardSheet.h
new file mode 100644 (file)
index 0000000..41b15d8
--- /dev/null
@@ -0,0 +1,42 @@
+
+#ifndef __TestWizardSheet_h__
+#define __TestWizardSheet_h__
+
+
+#include "TestWizardWelcomePage.h"
+#include "TestWizardPathFilterPage.h"
+#include "TestWizardFilePreviewPage.h"
+#include "TestWizardOutputPage.h"
+#include "TestWizardCompletionPage.h"
+
+class CTestWizardSheet :
+       public CWizard97SheetImpl<CTestWizardSheet>,
+       public CTestWizardInfoRef
+{
+protected:
+// Typedefs
+       typedef CTestWizardSheet thisClass;
+       typedef CWizard97SheetImpl<CTestWizardSheet> baseClass;
+       typedef CTestWizardInfoRef infoRefClass;
+
+// Data members
+       CTestWizardWelcomePage m_pageWelcome;
+       CTestWizardPathFilterPage m_pagePathFiler;
+       CTestWizardFilePreviewPage m_pageFilePreview;
+       CTestWizardOutputPage m_pageOutput;
+       CTestWizardCompletionPage m_pageCompletion;
+
+public:
+// Constructors
+       CTestWizardSheet(CTestWizardInfo* pTestWizardInfo, UINT uStartPage = 0, HWND hWndParent = NULL);
+
+// Message Handlers
+       BEGIN_MSG_MAP(thisClass)
+               MESSAGE_HANDLER(WM_HELP, OnHelp)
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+};
+
+#endif // __TestWizardSheet_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardWelcomePage.cpp b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardWelcomePage.cpp
new file mode 100644 (file)
index 0000000..46248dd
--- /dev/null
@@ -0,0 +1,89 @@
+
+#include "stdafx.h"
+#include "TestWizardWelcomePage.h"
+
+LRESULT CTestWizardWelcomePage::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+       this->InitializeControls();
+       this->InitializeValues();
+
+       return 1;
+}
+
+void CTestWizardWelcomePage::InitializeControls(void)
+{
+       CFontHandle fontExteriorPageTitleFont(baseClass::GetExteriorPageTitleFont());
+       CFontHandle fontBulletFont(baseClass::GetBulletFont());
+
+       CWindow title = this->GetDlgItem(IDC_WIZ97_EXTERIOR_TITLE);
+       CWindow bullet1 = this->GetDlgItem(IDC_WIZ97_BULLET1);
+       CWindow bullet2 = this->GetDlgItem(IDC_WIZ97_BULLET2);
+       CWindow bullet3 = this->GetDlgItem(IDC_WIZ97_BULLET3);
+       CWindow bullet4 = this->GetDlgItem(IDC_WIZ97_BULLET4);
+       m_buttonSkipWelcome = this->GetDlgItem(IDC_WIZ97_WELCOME_NOTAGAIN);
+
+       title.SetFont(fontExteriorPageTitleFont);
+       bullet1.SetFont(fontBulletFont);
+       bullet2.SetFont(fontBulletFont);
+       bullet3.SetFont(fontBulletFont);
+       bullet4.SetFont(fontBulletFont);
+}
+
+void CTestWizardWelcomePage::InitializeValues(void)
+{
+       bool showWelcome = m_pTestWizardInfo->GetShowWelcome();
+       m_buttonSkipWelcome.SetCheck(showWelcome ? BST_UNCHECKED : BST_CHECKED);
+}
+
+bool CTestWizardWelcomePage::StoreValues(void)
+{
+       m_pTestWizardInfo->SetShowWelcome(m_buttonSkipWelcome.GetCheck() == BST_UNCHECKED);
+       return true;
+}
+
+// Overrides from base class
+int CTestWizardWelcomePage::OnSetActive()
+{
+       this->SetWizardButtons(PSWIZB_NEXT);
+
+       // 0 = allow activate
+       // -1 = go back to page that was active
+       // page ID = jump to page
+       int result = 0;
+
+       if(m_allowWelcomeToHide)
+       {
+               // Have it so that the welcome page is only hidden on
+               // the first access, but is available if the user goes
+               // "back" to visit it.
+               m_allowWelcomeToHide = false;
+               if(m_buttonSkipWelcome.GetCheck() == BST_CHECKED)
+               {
+                       result = IDD_WIZ97_PATHFILTER;
+               }
+       }
+
+       return result;
+}
+
+int CTestWizardWelcomePage::OnWizardNext()
+{
+       bool success = this->StoreValues();
+       if(!success)
+       {
+               // Any errors are already reported, and if appropriate,
+               // the control that needs attention has been given focus.
+               return -1;
+       }
+
+       // 0  = goto next page
+       // -1 = prevent page change
+       // >0 = jump to page by dlg ID
+
+       return m_pTestWizardInfo->FindNextPage(IDD);
+}
+
+void CTestWizardWelcomePage::OnHelp()
+{
+       m_pTestWizardInfo->ShowHelp(IDD);
+}
diff --git a/include/WTL/Samples/Wizard97Test/Wizard/TestWizardWelcomePage.h b/include/WTL/Samples/Wizard97Test/Wizard/TestWizardWelcomePage.h
new file mode 100644 (file)
index 0000000..f8ebd3e
--- /dev/null
@@ -0,0 +1,48 @@
+
+#ifndef __TestWizardWelcomePage_h__
+#define __TestWizardWelcomePage_h__
+
+#include "TestWizardInfo.h"
+
+class CTestWizardWelcomePage :
+       public CWizard97ExteriorPageImpl<CTestWizardWelcomePage>,
+       public CTestWizardInfoRef
+{
+protected:
+// Typedefs
+       typedef CTestWizardWelcomePage thisClass;
+       typedef CWizard97ExteriorPageImpl<CTestWizardWelcomePage> baseClass;
+
+// Data members
+       CButton m_buttonSkipWelcome;
+       bool m_allowWelcomeToHide;
+
+public:
+// Constructors
+       CTestWizardWelcomePage(_U_STRINGorID title = (LPCTSTR)NULL) :
+               baseClass(title),
+               m_allowWelcomeToHide(true)
+       { }
+
+// Message Handlers
+       enum { IDD = IDD_WIZ97_WELCOME };
+       BEGIN_MSG_MAP(thisClass)
+               MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+
+               CHAIN_MSG_MAP(baseClass)
+       END_MSG_MAP()
+
+       LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+// Helper methods
+       void InitializeControls(void);
+       void InitializeValues(void);
+       bool StoreValues(void);
+
+// Overrides from base class
+       int OnSetActive();
+       int OnWizardNext();
+       void OnHelp();
+};
+
+#endif // __TestWizardWelcomePage_h__
diff --git a/include/WTL/Samples/Wizard97Test/Wizard97Test.cpp b/include/WTL/Samples/Wizard97Test/Wizard97Test.cpp
new file mode 100644 (file)
index 0000000..1434c01
--- /dev/null
@@ -0,0 +1,49 @@
+// Wizard97Test.cpp : main source file for Wizard97Test.exe
+//
+
+#include "stdafx.h"
+
+#include "resource.h"
+
+#include "Wizard\TestWizard.h"
+
+CAppModule _Module;
+
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)
+{
+       HRESULT hRes = ::OleInitialize(NULL);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
+       ::DefWindowProc(NULL, 0, 0, 0L);
+
+       AtlInitCommonControls(
+               ICC_WIN95_CLASSES |
+               ICC_DATE_CLASSES |
+               ICC_USEREX_CLASSES |
+               ICC_COOL_CLASSES |
+               ICC_PAGESCROLLER_CLASS |
+               ICC_NATIVEFNTCTL_CLASS);
+
+       // We use a RichEdit control
+       HINSTANCE hInstRich = ::LoadLibrary(CRichEditCtrl::GetLibraryName());
+       ATLASSERT(hInstRich != NULL);
+
+       hRes = _Module.Init(NULL, hInstance);
+       ATLASSERT(SUCCEEDED(hRes));
+
+       int nRet = 0;
+       // BLOCK: Run application
+       {
+               CTestWizard wizard;
+               wizard.ExecuteWizard();
+       }
+
+       ::FreeLibrary(hInstRich);
+
+       _Module.Term();
+       ::OleUninitialize();
+
+       return nRet;
+}
diff --git a/include/WTL/Samples/Wizard97Test/Wizard97Test.h b/include/WTL/Samples/Wizard97Test/Wizard97Test.h
new file mode 100644 (file)
index 0000000..fb445f6
--- /dev/null
@@ -0,0 +1 @@
+// Wizard97Test.h
diff --git a/include/WTL/Samples/Wizard97Test/Wizard97Test.sln b/include/WTL/Samples/Wizard97Test/Wizard97Test.sln
new file mode 100644 (file)
index 0000000..5f768be
--- /dev/null
@@ -0,0 +1,30 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Wizard97Test", "Wizard97Test.vcproj", "{AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}"
+EndProject
+Global
+       GlobalSection(DPCodeReviewSolutionGUID) = preSolution
+               DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000}
+       EndGlobalSection
+       GlobalSection(SolutionConfiguration) = preSolution
+               ConfigName.0 = Debug
+               ConfigName.1 = Release
+               ConfigName.2 = Unicode Debug
+               ConfigName.3 = Unicode Release
+       EndGlobalSection
+       GlobalSection(ProjectDependencies) = postSolution
+       EndGlobalSection
+       GlobalSection(ProjectConfiguration) = postSolution
+               {AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}.Debug.ActiveCfg = Debug|Win32
+               {AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}.Debug.Build.0 = Debug|Win32
+               {AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}.Release.ActiveCfg = Release|Win32
+               {AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}.Release.Build.0 = Release|Win32
+               {AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}.Unicode Debug.ActiveCfg = Unicode Debug|Win32
+               {AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}.Unicode Debug.Build.0 = Unicode Debug|Win32
+               {AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}.Unicode Release.ActiveCfg = Unicode Release|Win32
+               {AADB8628-DC1E-4AC9-ABE6-0C692A68F56F}.Unicode Release.Build.0 = Unicode Release|Win32
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+       EndGlobalSection
+       GlobalSection(ExtensibilityAddIns) = postSolution
+       EndGlobalSection
+EndGlobal
diff --git a/include/WTL/Samples/Wizard97Test/help/Context.h b/include/WTL/Samples/Wizard97Test/help/Context.h
new file mode 100644 (file)
index 0000000..1f9b2ac
--- /dev/null
@@ -0,0 +1 @@
+#include "..\resource.hm"
diff --git a/include/WTL/Samples/Wizard97Test/help/readme-help.txt b/include/WTL/Samples/Wizard97Test/help/readme-help.txt
new file mode 100644 (file)
index 0000000..1a1b3ab
--- /dev/null
@@ -0,0 +1,9 @@
+To compile the HtmlHelp file into the .chm, use the free HTML Help Workshop from Microsoft.
+Currently, you can download this from
+       http://msdn.microsoft.com/library/default.asp?url=/library/en-us/htmlhelp/html/hwMicrosoftHTMLHelpDownloads.asp
+or
+       http://go.microsoft.com/fwlink/?LinkId=14188
+or
+       http://www.microsoft.com/downloads/details.aspx?FamilyID=00535334-c8a6-452f-9aa0-d597d16580cc&DisplayLang=en
+or
+       http://download.microsoft.com/download/0/a/9/0a939ef6-e31c-430f-a3df-dfae7960d564/htmlhelp.exe
\ No newline at end of file
diff --git a/include/WTL/Samples/Wizard97Test/res/Wizard97Test.ico b/include/WTL/Samples/Wizard97Test/res/Wizard97Test.ico
new file mode 100644 (file)
index 0000000..3b11c7a
Binary files /dev/null and b/include/WTL/Samples/Wizard97Test/res/Wizard97Test.ico differ
diff --git a/include/WTL/Samples/Wizard97Test/res/header.bmp b/include/WTL/Samples/Wizard97Test/res/header.bmp
new file mode 100644 (file)
index 0000000..75b5691
Binary files /dev/null and b/include/WTL/Samples/Wizard97Test/res/header.bmp differ
diff --git a/include/WTL/Samples/Wizard97Test/res/watermark.bmp b/include/WTL/Samples/Wizard97Test/res/watermark.bmp
new file mode 100644 (file)
index 0000000..cb1bca0
Binary files /dev/null and b/include/WTL/Samples/Wizard97Test/res/watermark.bmp differ
diff --git a/include/WTL/Samples/Wizard97Test/resource.h b/include/WTL/Samples/Wizard97Test/resource.h
new file mode 100644 (file)
index 0000000..aa557e7
--- /dev/null
@@ -0,0 +1,71 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Wizard97Test.rc
+//
+#define IDD_WIZ97_INTERIOR_BLANK        110
+#define IDD_WIZ97_EXTERIOR_BLANK        111
+#define IDD_WIZ97_WELCOME               115
+#define IDD_WIZ97_COMPLETION            116
+#define IDD_WIZ97_PATHFILTER            117
+#define IDD_WIZ97_FILEPREVIEW           118
+#define IDD_WIZ97_OUTPUT                119
+
+#define IDB_WIZ97_HEADER                1000
+#define IDB_WIZ97_WATERMARK             1001
+
+#define IDC_WIZ97_EXTERIOR_TITLE        1004
+#define IDC_WIZ97_EXTERIOR_DESC         1005
+#define IDC_WIZ97_WELCOME_NOTAGAIN      1006
+#define IDC_WIZ97_SUMMARY               1007
+#define IDC_WIZ97_EXTERIOR_CLICKFINISH  1008
+#define IDC_WIZ97_BULLET1               1011
+#define IDC_WIZ97_BULLET2               1012
+#define IDC_WIZ97_BULLET3               1013
+#define IDC_WIZ97_BULLET4               1014
+#define IDC_WIZ97_BULLET5               1015
+#define IDC_WIZ97_BULLET6               1016
+#define IDC_WIZ97_BULLET7               1017
+#define IDC_WIZ97_BULLET8               1018
+#define IDC_WIZ97_BULLET9               1019
+#define IDC_WIZ97_BULLET1_DESC          1021
+#define IDC_WIZ97_BULLET2_DESC          1022
+#define IDC_WIZ97_BULLET3_DESC          1023
+#define IDC_WIZ97_BULLET4_DESC          1024
+#define IDC_WIZ97_BULLET5_DESC          1025
+#define IDC_WIZ97_BULLET6_DESC          1026
+#define IDC_WIZ97_BULLET7_DESC          1027
+#define IDC_WIZ97_BULLET8_DESC          1028
+#define IDC_WIZ97_BULLET9_DESC          1029
+#define IDC_LABEL_DESCRIPTION           1101
+#define IDC_LABEL_PATH                  1102
+#define IDC_EDIT_PATH                   1103
+#define IDC_BTN_BROWSEPATH              1104
+#define IDC_RADIO_RECURSE               1105
+#define IDC_RADIO_NORECURSE             1106
+#define IDC_LABEL_FILTER                1107
+#define IDC_RADIO_FILTER_ALL            1108
+#define IDC_RADIO_FILTER_CUSTOM         1109
+#define IDC_EDIT_FILTER                 1110
+#define IDC_LIST_FILES                  1120
+#define IDC_BTN_ADD                     1121
+#define IDC_BTN_REMOVE                  1122
+#define IDC_BTN_PREVIEW                 1123
+#define IDC_RADIO_COPYTOCLIPBOARD       1200
+#define IDC_RADIO_SENDEMAIL             1201
+#define IDC_RADIO_SAVETOFILE            1202
+#define IDC_EDIT_SAVETOFILE             1203
+#define IDC_BTN_FILEBROWSE              1204
+#define IDC_LABEL_FILEENCODING          1205
+#define IDC_COMBO_FILEENCODING          1206
+#define IDC_LABEL_FILENAME              1207
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32772
+#define _APS_NEXT_CONTROL_VALUE         1208
+#define _APS_NEXT_SYMED_VALUE           201
+#endif
+#endif
diff --git a/include/WTL/Samples/Wizard97Test/stdafx.cpp b/include/WTL/Samples/Wizard97Test/stdafx.cpp
new file mode 100644 (file)
index 0000000..80ca3f7
--- /dev/null
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     Wizard97Test.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#if (_ATL_VER < 0x0700)
+#include <atlimpl.cpp>
+#endif //(_ATL_VER < 0x0700)
diff --git a/include/WTL/Samples/Wizard97Test/stdafx.h b/include/WTL/Samples/Wizard97Test/stdafx.h
new file mode 100644 (file)
index 0000000..4d85bd8
--- /dev/null
@@ -0,0 +1,65 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__215476E2_9EAF_445C_9A58_E8CBCF4461AE__INCLUDED_)
+#define AFX_STDAFX_H__215476E2_9EAF_445C_9A58_E8CBCF4461AE__INCLUDED_
+
+#pragma once
+
+// Preprocessor definitions
+#ifndef STRICT
+#define STRICT
+#endif
+
+#define WINVER        0x0500
+#define _WIN32_WINNT  0x0500  // Require Windows 2000 or later
+#define _WIN32_IE     0x0501  // Require IE 5.01 or later (comes with Windows 2000 or later)
+#define _RICHEDIT_VER 0x0300  // Require RichEdit 3.0 or later (comes with Windows 2000 or later)
+
+// ATL related preprocessor definitions
+#if (_ATL_VER >= 0x0700)
+       #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // some CString constructors will be explicit
+       #define _ATL_USE_CSTRING_FLOAT
+       #define _ATL_USE_DDX_FLOAT
+       #define _ATL_NO_OLD_NAMES
+       #define _ATL_DISABLE_DEPRECATED
+       #define _ATL_ALL_WARNINGS
+       #define _ATL_NO_OLD_HEADERS_WIN64
+#endif
+
+// Includes
+#include "resource.h"
+
+#include <atlbase.h>
+#if (_ATL_VER >= 0x0700)
+       #include <atlstr.h>
+       #include <atltypes.h>
+#endif
+
+// WTL related preprocessor definitions
+#if (_ATL_VER >= 0x0700)
+       #define _WTL_NO_WTYPES
+       #define _WTL_NO_UNION_CLASSES
+       #define _WTL_NO_CSTRING
+#endif
+#define _WTL_NEW_PAGE_NOTIFY_HANDLERS
+
+#include <atlapp.h>
+extern CAppModule _Module;
+
+#include <atlwin.h>
+#include <atlcom.h>
+
+#include <atlmisc.h>
+#include <atlctl.h>
+#include <atlframe.h>
+#include <atlddx.h>
+#include <atldlgs.h>
+#include <atlctrls.h>
+#include <atlctrlw.h>
+#include <atlctrlx.h>
+#include <atlscrl.h>
+
+#endif // !defined(AFX_STDAFX_H__215476E2_9EAF_445C_9A58_E8CBCF4461AE__INCLUDED_)
diff --git a/include/WTL/readme.htm b/include/WTL/readme.htm
new file mode 100644 (file)
index 0000000..70d9130
--- /dev/null
@@ -0,0 +1,3347 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>Windows Template Library</title>
+<style type="text/css">
+.style1 {
+       font-family: Arial;
+       font-weight: bold;
+       font-size: x-small;
+}
+.style2 {
+       font-family: Arial;
+       font-size: x-small;
+}
+.style3 {
+       text-align: right;
+}
+</style>
+</head>
+
+<body>
+
+<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber3">
+  <tr>
+    <td class="style3">
+       <p style="text-align: left"><font face="Arial"><b>Windows Template Library - WTL Version 8.1</b></font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+       (build 9127) 5/7/09</font></td>
+  </tr>
+  <tr>
+    <td><hr></td>
+  </tr>
+  <tr>
+    <td><font face="Arial" size="2">Copyright &#169; 2009 Microsoft Corporation.
+All rights reserved.</font></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+  </tr>
+  <tr>
+    <td><font face="Arial" size="2">This file is a part of the Windows Template 
+       Library.<br>
+       The use and distribution terms for this software are covered by the<br>
+       Common Public License 1.0 (<a target="_blank" href="http://opensource.org/licenses/cpl1.0.php">http://opensource.org/licenses/cpl1.0.php</a>)<br>
+       which can be found in the file CPL.TXT at the root of this distribution.<br>
+       By using this software in any fashion, you are agreeing to be bound by<br>
+       the terms of this license. You must not remove this notice, or<br>
+       any other, from this software.</font></td>
+  </tr>
+  <tr>
+    <td><hr></td>
+  </tr>
+</table>
+
+<p style=margin:0in>&nbsp;</p>
+
+<p style=margin:0in>&nbsp;</p>
+
+<p style=margin:0in><font face="Arial" size="2">Welcome to the Windows Template Library, version 
+8.1. This document contains the following topics:</font></p>
+<p style=margin:0in>&nbsp;</p>
+<ul style="margin-top:0in;margin-bottom:0in">
+       <li><font face="Arial" size="2"><a href="#Introduction">Introduction</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Features And Installation">Features 
+  And Installation</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Packing List">Packing List</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Class Overview">Class Overview</a></font></li>
+       <li><font face="Arial" size="2"><a href="#ATL/WTL AppWizard">ATL/WTL AppWizard</a></font></li>
+       <li><a href="#Support for Windows CE"><font face="Arial" size="2">S</font></a><font face="Arial" size="2"><a href="#Support for Windows CE">upport 
+  for Windows CE</a></font></li>
+       <li><font face="Arial" size="2">
+       <a href="#Support for Visual C++ 2005 Express">Support for Visual C++ 2005 
+       Express</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Notes">Notes</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Changes Between WTL 8.1 And 8.0">Changes Between WTL 
+       8.1 And 8.0</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Changes Between WTL 8.0 And 7.5">Changes Between WTL 
+       8.0 And 7.5</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Changes Between WTL 7.5 And 7.1">Changes Between WTL 7.5 And 7.1</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Changes Between WTL 7.1 And 7.0">Changes Between WTL 
+  7.1 And 7.0</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Changes Between WTL 7.0 And 3.1">Changes Between WTL 
+  7.0 And 3.1</a></font></li>
+       <li><font face="Arial" size="2"><a href="#Changes Between WTL 3.1 And 3.0">Changes Between WTL 3.1 And 3.0</a></font></li>
+</ul>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial">
+<b><a name="Introduction"></a>Introduction</b></font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">Windows Template Library, or WTL, is a set of 
+classes that extend ATL to support more complex user interfaces for either 
+applications or various UI components, while maintaining the big advantage of 
+ATL - small and fast code. WTL classes were designed to be the best and the 
+easiest way to implement rich Win32 based UI for ATL based applications, 
+servers, components, and controls.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">WTL provides support for implementing 
+many 
+user interface elements, from frame and popup windows, to MDI, standard and 
+common controls, common dialogs, property sheets and pages, GDI objects, UI 
+updating, scrollable windows, splitter windows, command bars, etc. The WTL 
+classes are mostly templated and use minimal instance data and inline functions. 
+They were not designed as a framework, so they do not force a particular 
+application model, and can accommodate any. The classes do not use hooks or 
+thread local storage, so they have no restrictions that those techniques impose. 
+They also have no inter-dependencies and can be freely mixed with straight SDK 
+code. In summary, WTL delivers very small and efficient code, very close in size 
+and speed to SDK programs, while presenting a more logical, object oriented 
+model to a programmer.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial">
+<b><a name="Features And Installation"></a>Features And Installation</b></font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">This is the sixth public release 
+of WTL, after WTL 3.0, 3.1, 7.0, 7.1, and 7.5. It is also the second release of WTL 
+under the Common Public License, enabling developers from the WTL community to 
+contribute to the library.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">WTL classes can be used with either VC++ 6.0 and ATL 3.0, VC++ .NET 
+2002 and ATL 7.0, VC++ .NET 2003 and ATL 7.1, VC++ 2005 with ATL 8.0, or EVC++ 4.0 or 3.0 with ATL for 
+Windows CE. AppWizard for VC++ .NET 2002 and 2003, and Visual C++ 2005 is 
+included.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">The WTL classes are provided in 
+header files located in the include directory. The only header files that must 
+be included is atlapp.h, while others can be used when needed. The name of the 
+file doesn't mean that you have to create an application, just that 
+atlapp.h contains base definitions required for WTL projects.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">To install WTL, just copy the whole directory 
+structure, or unpack the archive file, to the location of your choice. Please be sure to
+<b>add the WTL\include 
+directory</b> to the list of include directories in VC++, so that the compiler 
+can find them when you include them in your projects..</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">Setup programs for the AppWizard are provided. After executing the setup scripts, ATL/WTL AppWizard will appear in the list of AppWizards when you select File.New.Project 
+in VC++ IDE. The file AppWiz\setup70.js is the setup script for VC++ .NET 2002, AppWiz\setup71.js is for VC++ 
+.NET 2003, and AppWiz\setup80.js is for VC++ 2005. AppWizCE\setup80.js is setup 
+script for VC++ 2005 SmartDevice projects.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">To manually install AppWizard 
+for VC++ .NET 2002/2003, copy all WTLAppWiz.* files from AppWiz\Files to VC++ .NET 
+projects directory, %VC7DIR%\Vc7\vcprojects, where %VC7DIR% is the directory 
+where VC++ .NET 2002/2003 is installed. After that,&nbsp;open WTLAppWiz.vsz and modify the 
+like that contains ABSOLUTE_PATH to contain %WTLDIR%\AppWiz\Files, where 
+%WTLDIR% is the directory where WTL files are.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">Platform support and 
+requirements:</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Compiler/IDE/ATL:</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+Visual C++ 6.0&nbsp;&nbsp; (ATL 3.0)</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+Visual C++.NET 2002&nbsp;&nbsp; (ATL 7.0)</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+Visual C++.NET 2003&nbsp;&nbsp; (ATL 7.1)</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+Visual C++ 2005&nbsp;&nbsp; (ATL 8.0)</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; SDK 
+(optional):</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+Any Platform SDK from January 2000 release up to the latest Windows SDK</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Windows CE 
+development:</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+eMbedded Visual C++ 3.0 - Pocket PC, Pocket PC 2002</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+eMbedded Visual C++ 4.0 - STANDARDSDK_410, Pocket PC 2003, Smartphone 2003,
+</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+STANDARDSDK_500, Pocket PC 2003 SE, Smartphone 2003 SE</font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+Visual C++ 2005 - Pocket PC 2003 SE, Smartphone 2003 SE, STANDARDSDK_500,</font></p>
+<p style=margin:0in><span class="style2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span><font face="Arial" size="2">Windows Mobile 5.0 (Pocket PC and Smartphone),<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+Windows Mobile 6.0 (Standard and Professional)</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial">
+<b><a name="Packing List"></a>Packing List</b></font></p>
+<p style=margin:0in>&nbsp;</p>
+<table border="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="497" id="AutoNumber2">
+  <tr>
+    <td width="136"><font face="Arial" size="2">File Name</font><font face="Arial">:</font></td>
+    <td width="358"><font face="Arial" size="2">Description:</font></td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2"><hr></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">readme.htm</font></td>
+    <td width="358"><font face="Arial" size="2">this file</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">CPL.TXT</font></td>
+    <td width="358"><font face="Arial" size="2">Common Public License</font></td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2">&nbsp;</td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2"><font face="Arial" size="2">include\</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlapp.h</font></td>
+    <td width="358"><font face="Arial" size="2">message loop, interfaces, 
+    general app stuff</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlcrack.h</font></td>
+    <td width="358"><font face="Arial" size="2">message cracker macros</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlctrls.h</font></td>
+    <td width="358"><font face="Arial" size="2">standard and common control 
+    classes</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlctrlw.h</font></td>
+    <td width="358"><font face="Arial" size="2">command bar class</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlctrlx.h</font></td>
+    <td width="358"><font face="Arial" size="2">bitmap button, check list view, 
+    and other controls</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlddx.h</font></td>
+    <td width="358"><font face="Arial" size="2">data exchange for dialogs and 
+    windows</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atldlgs.h</font></td>
+    <td width="358"><font face="Arial" size="2">common dialog classes, property 
+    sheet and page classes</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlfind.h</font></td>
+    <td width="358"><font face="Arial" size="2">Find/Replace support for Edit 
+       and RichEdit</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlframe.h</font></td>
+    <td width="358"><font face="Arial" size="2">frame window classes, MDI, 
+    update UI classes</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlgdi.h</font></td>
+    <td width="358"><font face="Arial" size="2">DC classes, GDI object classes</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlmisc.h</font></td>
+    <td width="358"><font face="Arial" size="2">WTL ports of CPoint, CRect, 
+    CSize, CString, etc.</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlprint.h</font></td>
+    <td width="358"><font face="Arial" size="2">printing and print preview</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlres.h</font></td>
+    <td width="358"><font face="Arial" size="2">standard resource IDs</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlresce.h</font></td>
+    <td width="358"><font face="Arial" size="2">standard resource IDs for 
+    Windows CE</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlscrl.h</font></td>
+    <td width="358"><font face="Arial" size="2">scrollable windows</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlsplit.h</font></td>
+    <td width="358"><font face="Arial" size="2">splitter windows</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atltheme.h</font></td>
+    <td width="358"><font face="Arial" size="2">Windows XP theme classes</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atluser.h</font></td>
+    <td width="358"><font face="Arial" size="2">menu class, USER object classes</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlwince.h</font></td>
+    <td width="358"><font face="Arial" size="2">specific support for Windows CE 
+       Mobile platforms</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlwinx.h</font></td>
+    <td width="358"><font face="Arial" size="2">extensions of ATL windowing 
+    support</font></td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2">&nbsp;</td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2"><font face="Arial" size="2">Samples\</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Aero\...</font></td>
+    <td width="358"><font face="Arial" size="2">Vista Aero glass showcase</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Alpha\...</font></td>
+    <td width="358"><font face="Arial" size="2">Windows XP 32-bit (alpha) 
+    toolbar images</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; BmpView\...</font></td>
+    <td width="358"><font face="Arial" size="2">bitmap file view sample</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; GuidGen\...</font></td>
+    <td width="358"><font face="Arial" size="2">WTL version of the GuidGen 
+    sample</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; ImageView\...</font></td>
+    <td width="358"><font face="Arial" size="2">Full-featured PPC frame-view 
+       application</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; MDIDocVw\...</font></td>
+    <td width="358"><font face="Arial" size="2">WTL version of the MDI sample</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; MiniPie\...</font></td>
+    <td width="358" class="style2">p<font size="2">ort of the SDK sample for 
+       Mobile devices</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; MTPad\...</font></td>
+    <td width="358"><font face="Arial" size="2">multithreaded notepad sample</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; SPControls\...</font></td>
+    <td width="358"><font face="Arial" size="2">Barebone SmartPhone dialog 
+       application</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; TabBrowser\...</font></td>
+    <td width="358"><font face="Arial" size="2">Web browser using TabView</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Wizard97Test\...</font></td>
+    <td width="358"><font face="Arial" size="2">Wizard97 showcase 
+    sample</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; WTLExplorer\...</font></td>
+    <td width="358"><font face="Arial" size="2">Explorer-like application 
+    sample</font></td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2">&nbsp;</td>
+  </tr>
+       <tr>
+    <td width="494" colspan="2"><font face="Arial" size="2">AppWiz\</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup70.js</font></td>
+    <td width="358"><font face="Arial" size="2">AppWizard setup program for VC++ 
+    .NET 2002</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup71.js</font></td>
+    <td width="358"><font face="Arial" size="2">AppWizard setup program for VC++ 
+    .NET 2003</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup80.js</font></td>
+    <td width="358"><font face="Arial" size="2">AppWizard setup program for VC++ 
+    2005</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup80x.js</font></td>
+    <td width="358"><font face="Arial" size="2">AppWizard setup program for VC++ 
+    2005 Express</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Files\...</font></td>
+    <td width="358"><font face="Arial" size="2">WTL AppWizard for VC++ .NET 2002 and 
+    2003 files</font></td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2">&nbsp;</td>
+  </tr>
+       <tr>
+    <td width="494" colspan="2"><font face="Arial" size="2">AppWizCE\</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup80.js</font></td>
+    <td width="358"><font face="Arial" size="2">AppWizard setup program for VC++ 
+    2005</font></td>
+  </tr>
+       <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Files\...</font></td>
+    <td width="358"><font face="Arial" size="2">WTL AppWizard for VC++ 2005 files</font></td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2">&nbsp;</td>
+  </tr>
+  <tr>
+    <td width="494" colspan="2"><font face="Arial" size="2">AppWizMobile\</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup80.js</font></td>
+    <td width="358"><font face="Arial" size="2">AppWizard Mobile setup program for VC++ 
+    2005</font></td>
+  </tr>
+  <tr>
+    <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Files\...</font></td>
+    <td width="358"><font face="Arial" size="2">WTL AppWizard Mobile for VC++ 2005 files</font></td>
+  </tr>
+  </table>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial">
+<b><a name="Class Overview"></a>Class Overview</b></font></p>
+<p style=margin:0in>&nbsp;</p>
+<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber4">
+  <tr>
+    <td><font face="Arial" size="2">usage:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+    </font></td>
+    <td><font face="Arial" size="2"><b>mi base</b></font></td>
+    <td>&nbsp;&nbsp; -</td>
+    <td><font face="Arial" size="2">&nbsp;&nbsp; a base class (multiple 
+    inheritance)</font></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td><font face="Arial" size="2"><b>client</b></font></td>
+    <td>&nbsp;&nbsp; -</td>
+    <td><font face="Arial" size="2">&nbsp;&nbsp; wrapper class for a handle</font></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td><font face="Arial" size="2"><b>as-is</b></font></td>
+    <td>&nbsp;&nbsp; -</td>
+    <td><font face="Arial" size="2">&nbsp;&nbsp; to be used directly</font></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td><font face="Arial" size="2"><b>impl</b></font></td>
+    <td>&nbsp;&nbsp; -</td>
+    <td><font face="Arial" size="2">&nbsp;&nbsp; implements a window (has 
+    WindowProc) or other support</font></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td><font face="Arial" size="2"><b>helper</b></font></td>
+    <td>&nbsp;&nbsp; -</td>
+    <td><font face="Arial" size="2">&nbsp;&nbsp; a helper class</font></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td><font face="Arial" size="2"><b>base</b></font></td>
+    <td>&nbsp;&nbsp; -</td>
+    <td><font face="Arial" size="2">&nbsp;&nbsp; implementation base class</font></td>
+  </tr>
+</table>
+<p style=margin:0in>&nbsp;</p>
+<table border="1" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber1" width="600">
+  <tr>
+    <td width="220"><b><font face="Arial" size="2">class name:</font></b></td>
+    <td width="114"><b><font face="Arial" size="2">usage:</font></b></td>
+    <td width="253"><b><font face="Arial" size="2">description:</font></b></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font size="2" face="Arial"><br>App/module support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CAppModule</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">app support, CComModule derived</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CServerAppModule</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">module for COM servers</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMessageLoop</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">message loop</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMessageFilter</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi base</font></td>
+    <td width="255"><font face="Arial" size="2">message filter interface</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CIdleHandler</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi base</font></td>
+    <td width="255"><font face="Arial" size="2">idle time handler interface</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Frame windows</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFrameWindowImplBase</font></b></td>
+    <td width="115"><font face="Arial" size="2">base</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFrameWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">frame window support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">COwnerDraw</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi base</font></td>
+    <td width="255"><font face="Arial" size="2">owner-draw msg map and handlers</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CDialogResize</font>
+    </b></td>
+    <td width="115"><font face="Arial" size="2">impl mi base</font></td>
+    <td width="255"><font face="Arial" size="2">support for resizing dialogs</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CDoubleBufferImpl</font>
+    </b></td>
+    <td width="115"><font face="Arial" size="2">impl mi</font></td>
+    <td width="255"><font face="Arial" size="2">double-buffer painting support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CDoubleBufferWindowImpl</font>
+    </b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">double-buffer painting window</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>MDI windows</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMDIWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">MDI methods</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMDIFrameWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">MDI frame window</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMDIChildWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">MDI child window</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Update UI</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CUpdateUIBase</font></b></td>
+    <td width="115"><font face="Arial" size="2">base</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CUpdateUI</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi base class</font></td>
+    <td width="255"><font face="Arial" size="2">provides support for UI update</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CDynamicUpdateUI</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi base class</font></td>
+    <td width="255"><font face="Arial" size="2">provides dynamic support for UI update</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Standard controls</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CStatic</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">static ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CButton</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">button ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CListBox</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">list box ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CComboBox</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">combo box ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CEdit</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">edit ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CEditCommands</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255"><font face="Arial" size="2">standard edit command support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CScrollBar</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">scroll bar ctrl</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Common controls</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CImageList</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">image list</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CListViewCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">list view ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CTreeViewCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">tree view ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CTreeItem</font></b></td>
+    <td width="115"><font face="Arial" size="2">helper</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CTreeViewCtrlEx</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">uses CTreeItem</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CHeaderCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">header bar ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CToolBarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">toolbar ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CStatusBarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">status bar ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CTabCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">tab ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CToolTipCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">tool tip ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CToolInfo</font></b></td>
+    <td width="115"><font face="Arial" size="2">helper</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CTrackBarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">trackbar ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CUpDownCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">up-down ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CProgressBarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">progress bar ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CHotKeyCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">hot key ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CAnimateCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">animation ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CRichEditCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">rich edit ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CRichEditCommands</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255"><font face="Arial" size="2">std rich edit commands support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CDragListBox</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">drag list box</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CDragListNotifyImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi class</font></td>
+    <td width="255"><font face="Arial" size="2">support for notifications</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CReBarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">rebar ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CComboBoxEx</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">extended combo box</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CDateTimePickerCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">date-time ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFlatScrollBarImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi impl</font></td>
+    <td width="255"><font face="Arial" size="2">flat scroll bars support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFlatScrollBar</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">flat scroll bars support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CIPAddressCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">IP address ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMonthCalendarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">month calendar ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CCustomDraw</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi class</font></td>
+    <td width="255"><font face="Arial" size="2">custom draw handling support</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Windows CE controls</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CCECommandBarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">command bar ctrl</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CCECommandBandsCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">command bands ctrl</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Property sheet &amp; page</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPropertySheetWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPropertySheetImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">property sheet </font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPropertySheet</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPropertyPageWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPropertyPageImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">property page</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPropertyPage</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CAxPropertyPageImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">property page with ActiveX</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CAxPropertyPage</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CWizard97SheetWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CWizard97SheetImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Wizard97 property sheet</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CWizard97Sheet</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CWizard97PageWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CWizard97PageImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Wizard97 property page</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CWizard97ExteriorPageImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Wizard97 exterior page</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CWizard97InteriorPageImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Wizard97 interior page</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAeroWizardFrameWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAeroWizardFrameImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Aero Wizard frame</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAeroWizardFrame</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAeroWizardPageWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAeroWizardPageImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Aero Wizard page</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAeroWizardPage</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAeroWizardAxPageImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Aero Wizard page with ActiveX</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAeroWizardAxPage</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Common dialogs</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFileDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">GetOpenFileName/GetSaveFileName</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CFileDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMultiFileDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Multi-select GetOpenFileName</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMultiFileDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CShellFileDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">base</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CShellFileOpenDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Shell File Open dialog</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CShellFileOpenDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CShellFileSaveDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Shell File Save dialog</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CShellFileSaveDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFolderDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">directory picker</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFolderDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFontDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">ChooseFont common dialog</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFontDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CRichEditFontDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">ChooseFont for rich edit</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CRichEditFontDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CColorDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">ChooseColor common dialog</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CColorDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">PrintDlg common dialog</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintDialogExImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">new Win2000 print dialog</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintDialogEx</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPageSetupDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">PageSetupDlg common dialog</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPageSetupDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFindReplaceDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">FindText/ReplaceText</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFindReplaceDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>User support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMenu</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">menu support</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CMenuItemInfo</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">MENUITEMINFO wrapper</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAccelerator</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">accelerator table</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CIcon</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">icon object</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CCursor</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">cursor object</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CResource</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">generic resource object</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>GDI support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CDC</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">DC support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPaintDC</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">for handling WM_PAINT</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CClientDC</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">for GetDC</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CWindowDC</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">for GetWindowDC</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMemoryDC</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">in-memory DC</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPen</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">GDI pen object</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CBrush</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">GDI brush object</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CLogFont</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">LOGFONT wrapper</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CFont</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">GDI font object</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CBitmap</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">GDI bitmap object</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPalette</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">GDI palette object</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CRgn</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">GDI region object</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Enhanced controls</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CCommandBarCtrlImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">command bar</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CCommandBarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CBitmapButtonImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">bitmap button</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CBitmapButton</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CCheckListViewCtrlImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">check list box</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CCheckListViewCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CHyperLinkImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">hyper link control</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CHyperLink</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CWaitCursor</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">wait cursor</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CCustomWaitCursor</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">custom and animated wait cursor</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMultiPaneStatusBarCtrlImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">status bar with multiple panes</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMultiPaneStatusBarCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPaneContainerImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">pane window container</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPaneContainer</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CSortListViewImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">sorting list view control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CSortListViewCtrlImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CSortListViewCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CTabViewImpl;</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">tab view window</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CTabView</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Scrolling window support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CScrollImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi</font></td>
+    <td width="255"><font face="Arial" size="2">scrolling support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CScrollWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">scrollable window</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMapScrollImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi</font></td>
+    <td width="255"><font face="Arial" size="2">scrolling support with map modes</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CMapScrollWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">scrollable window with map modes</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CZoomScrollImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi</font></td>
+    <td width="255"><font face="Arial" size="2">zooming support</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CZoomScrollWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">zooming window</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CScrollContainerImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">scroll container window</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CScrollContainer</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Splitter window support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CSplitterImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi</font></td>
+    <td width="255"><font face="Arial" size="2">splitter support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CSplitterWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">splitter window</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CSplitterWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Theming support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CTheme</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">Windows XP theme</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CThemeImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">theming support for a window</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Buffered paint and animation support</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CBufferedPaint</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">buffered paint</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CBufferedPaintImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi</font></td>
+    <td width="255"><font face="Arial" size="2">buffered paint support</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CBufferedPaintWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">window with buffered paint</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CBufferedAnimation</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255" class="style2">b<font size="2">uffered animation</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CBufferedAnimationImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl mi</font></td>
+    <td width="255"><font face="Arial" size="2">buffered animation support</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CBufferedAnimationWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">window with buffered animation</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Edit and RichEdit Find/Replace support</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CEditFindReplaceImplBase</font></b></td>
+    <td width="115"><font face="Arial" size="2">base</font></td>
+    <td width="255" class="style2">&nbsp;</td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CEditFindReplaceImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255"><font face="Arial" size="2">Edit Find/Replace support</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CRichEditFindReplaceImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255" class="style2"><font face="Arial" size="2">RichEdit Find/Replace support</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Printing support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrinterInfo</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">print info support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrinter</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">printer handle wrapper</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CDevMode</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">DEVMODE wrapper</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrinterDC</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">printing DC support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintJobInfo</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">print job info</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintJob</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">print job support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintPreview</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255"><font face="Arial" size="2">print preview support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintPreviewWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">print preview window</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CPrintPreviewWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CZoomPrintPreviewWindowImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">zooming print preview window</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CZoomPrintPreviewWindow</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Miscellaneous</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CSize</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">WTL port of MFC's CSize</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CPoint</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">WTL port of MFC's CPoint</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CRect</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">WTL port of MFC's CRect</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CString</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">WTL port of MFC's CString</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CWinDataExchange</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255"><font face="Arial" size="2">data exchange for controls</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CRecentDocumentList</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi or as-is</font></td>
+    <td width="255"><font face="Arial" size="2">support for MRU list</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CFindFile</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">file search support</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>In-memory dialog</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CMemDlgTemplate</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">In-memory dialog template</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CIndirectDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">In-memory dialog class</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Task dialog</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CTaskDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Task Dialog in Vista</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CTaskDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td colspan="3" width="593"><font face="Arial" size="2"><br>Windows CE support</font></td>
+  </tr>
+  <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdDialogBase</font></b></td>
+    <td width="115"><font face="Arial" size="2">base</font></td>
+    <td width="255"><font face="Arial" size="2">standard dialog base class</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">standard dialog implementation</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdSimpleDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">standard simple dialog</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdDialogResizeBase</font></b></td>
+    <td width="115"><font face="Arial" size="2">base</font></td>
+    <td width="255"><font face="Arial" size="2">orientation aware standard dialog base class</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdDialogResizeImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">orientation aware standard dialog implementation</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdSimpleDialogResizeImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">standard resizing simple dialog implementation</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdOrientedDialogBase</font></b></td>
+    <td width="115"><font face="Arial" size="2">base</font></td>
+    <td width="255"><font face="Arial" size="2">oriented dialog base class</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdOrientedDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">oriented dialog implementation</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CStdSimpleOrientedDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">as-is</font></td>
+    <td width="255"><font face="Arial" size="2">standard simple oriented dialog</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAppInfoBase</font></b></td>
+    <td width="115"><font face="Arial" size="2">base</font></td>
+    <td width="255"><font face="Arial" size="2">application state save/restore to registry</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAppInfoT</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">CAppInfoBase constructed from a CAppWindow&lt;T&gt;</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAppWindow&lt;&gt;</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255"><font face="Arial" size="2">PPC/SmartPhone well-behaved application window class</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAppDialog</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255"><font face="Arial" size="2">PPC/SmartPhone well-behaved application non-modal dialog class</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CAppStdDialogImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">PPC/SmartPhone implementation of non-modal standard dialog application</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CFullScreenFrame</font></b></td>
+    <td width="115"><font face="Arial" size="2">impl</font></td>
+    <td width="255"><font face="Arial" size="2">Full screen frame class</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CZoomScrollImpl</font></b></td>
+    <td width="115"><font face="Arial" size="2">mi</font></td>
+    <td width="255"><font face="Arial" size="2">WinCE zooming implementation</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CHtmlCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">HTML control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CRichInkCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">RichInk control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CInkXCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">InkX control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CVoiceRecorderCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">VoiceRecorder control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CDocListCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">DocList control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CCapEdit</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">CapEdit control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CTTStatic</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">TT Static control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CTTButton</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">TT Button control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CSpinCtrl</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">Spin control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CSpinListBox</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">Spin List Box control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CExpandListBox</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">Expand List Box control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CExpandEdit</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">Expand Edit control</font></td>
+  </tr>
+       <tr>
+    <td width="221"><b><font face="Arial" size="2">CExpandCapEdit</font></b></td>
+    <td width="115"><font face="Arial" size="2">client</font></td>
+    <td width="255"><font face="Arial" size="2">Expand CapEdit control</font></td>
+  </tr>
+</table>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial">
+<b><a name="ATL/WTL AppWizard"></a>ATL/WTL AppWizard</b></font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">ATL/WTL AppWizard generates starting code for a 
+WTL application. It has options to create code for different application types and features.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">You can choose the following options:</font></p>
+<ul style='margin-top:0in;margin-bottom:0in'>
+  <li><font face="Arial" size="2">Application type (SDI, multi thread SDI, MDI, 
+  TabView, Explorer, dialog based)</font></li>
+  <li><font face="Arial" size="2">Support for hosting ActiveX controls</font></li>
+  <li><font face="Arial" size="2">COM server support</font></li>
+  <li><font face="Arial" size="2">Class implementation in .CPP files</font></li>
+  <li><font face="Arial" size="2">Common Control manifest</font></li>
+       <li class="style2">U<font size="2">nicode character set</font></li>
+  <li><font face="Arial" size="2">Toolbar, rebar, command bar, status bar</font></li>
+  <li><font face="Arial" size="2">View window, and it's type (generic, dialog 
+  based form, or a list box, edit, list view, tree view, rich edit based, HTML 
+  page, scroll window)</font></li>
+  <li><font face="Arial" size="2">For dialog based apps or a form based view 
+  window - support for hosting ActiveX controls in the dialog</font></li>
+</ul>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">ATL/WTL AppWizard supports VC++ 
+.NET 2002 and 2003,and VC++ 2005.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Support for Windows CE"></a>Support for 
+Windows CE</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">WTL now fully supports building 
+projects for the Windows CE platforms. This initial support for Windows CE was implemented primarily for 
+eMbedded Visual C++ 4.0 with Pocket PC 2003 and 
+SmartPhone 2003 SDKs. However, it can be used with other versions and 
+configurations. For instance, Standard SDK 4.1 or 5.0 is supported as well. Considerable effort was made to provide the best Windows CE support, 
+however, there might be some limitations because different platforms provide different 
+programming support. SmartDevice projects with Visual Studio 2005 are also 
+supported, and it also includes an AppWizard for VS2005.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">The support for Windows CE was 
+not designed to port projects for the desktop version of Windows as-is to the 
+Windows CE platforms, but to allow use of the same library, WTL, for both 
+desktop Windows and Windows CE. Applications for Windows CE are often designed 
+in a different way, and they use different platform services. WTL depends on the 
+version of ATL provided with each Windows CE platform, and supports controls and 
+services that are appropriate and supported for each Windows CE platform.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Support for Visual C++ 2005 Express"></a>Support for 
+Visual C++ 2005 Express</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">WTL 8.0 supports using Visual 
+C++ Express Edition to build projects. Since Visual C++ 2005 Express ships without ATL, you have 
+to use a version of ATL that ships with the Platform SDK.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">The WTL App Wizard can be 
+installed by running AppWiz\setup80x.js program. The App Wizard generates code 
+in the stdafx.h file that allows use of ATL3 from the Platform SDK. That code is 
+used if WTL_USE_SDK_ATL3 is defined, so you can comment the line in stdafx.h 
+that defines WTL_USE_SDK_ATL3 to use the project with different versions of 
+Visual C++ or ATL.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">Note that Release builds will 
+generate some warnings, since ATL3 from Platform SDK is an old version of ATL 
+which doesn't quite match the newer compiler and CRT files. You can ignore those 
+warnings, as they do not indicate any real problems with the code.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Notes"></a>Notes</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; WTL provides 
+several classes that are also present in ATL 7.0 and 7.1. The classes are: <b>
+CSize</b>, <b>CPoint</b>, <b>CRect</b>, and <b>CString</b> in atlmisc.h. 
+While their existence will not cause any problems, their usage might. You should 
+qualify the class you want to use with a namespace to resolve ambiguity, either 
+ATL or WTL namespace, depending on which implementation you want to use. 
+Alternatively, you can conditionally exclude WTL implementations, by defining 
+preprocessor symbol <b>_WTL_NO_WTYPES</b> for CSize, CPoint, and CRect; and <b>_WTL_NO_CSTRING</b> 
+for CString.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; If 
+you use WTL 8.0 with VC++ 6.0/ATL 3.0 and define _ATL_STATIC_REGISTRY, you'll 
+get errors referring to the ambiguous symbol ATL. This is caused by a bug in ATL 
+3.0 - in atlbase.h, the file statreg.h is included inside of the ATL namespace, 
+and it contains another namespace ATL declaration. Because of that, the compiler 
+cannot decide between ATL:: and ATL::ATL:: namespaces. The solution is either to 
+fix the atlbase.h, or to surround atlbase.h include declaration with following 
+statements:</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2"><b>&nbsp;&nbsp;&nbsp; #define 
+ATL&nbsp;&nbsp; ATLFIX</b></font></p>
+<p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; #include &lt;atlapp.h&gt;</font></p>
+<p style=margin:0in><font face="Arial" size="2">
+<b>&nbsp;&nbsp;&nbsp; #undef ATL</b></font></p>
+<p style=margin:0in><font face="Arial" size="2">
+<b>&nbsp;&nbsp;&nbsp; namespace ATL = ::ATLFIX;</b></font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; 
+Windows XP allows applications to use Common Controls version 6, which supports 
+only Unicode applications. While WTL allows creation of Ansi applications that 
+use Common Controls 6, that should be used only for test programs and is not 
+recommended or supported for released projects. If you want to use Common 
+Controls 6, build your application as Unicode.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; 
+If you build your app that hosts ActiveX controls 
+with VC++ 7.x, you can see this assert failing:<br>
+<span class="style2"><strong><br>
+&nbsp;&nbsp;&nbsp; !InlineIsEqualGUID(*m_plibid, GUID_NULL) &amp;&amp; &quot;Did you forget 
+to pass the LIBID to CComModule::Init?&quot;<br>
+<br>
+</strong></span>There are two ways to fix this:</font></p>
+<ul>
+       <li>
+       <p style=margin:0in><span class="style2">In the main .CPP file of your 
+       project, replace the line<br>
+       <strong>&nbsp;&nbsp;&nbsp; hRes = _Module.Init(NULL, hInstance);<br>
+       </strong>with this one<br>
+       <strong>&nbsp;&nbsp;&nbsp; hRes = _Module.Init(NULL, hInstance, &amp;LIBID_ATLLib);<br>
+&nbsp;</strong></span></p>
+       </li>
+       <li>
+       <p style=margin:0in><span class="style2">Compile you project with _ATL_DLL 
+       defined (dynamic link to ATL)</span></p>
+       </li>
+</ul>
+<p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; 
+Several of the sample programs included with WTL were extended to support 
+building for Windows CE. These samples are not specially redesigned for Windows 
+CE, but just modified to allow you to compile and run them on the Windows CE 
+platforms. The samples are: BmpView, GuidGen, and MTPad.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; WTL 
+supports building projects with EVC++ 3.0 only for Pocket PC and Pocket PC 2002 
+platforms, as other platforms don't provide minimum support for ATL or other 
+required libraries.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; The 
+old AppWizards for VC++ 6.0 and eVC++ 4.0/3.0 are not included in this version 
+of WTL because they cannot be a part of an Open Source project. They are still 
+available in the previous release, WTL 7.1.</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Changes Between WTL 8.1 And 8.0"></a>Changes Between WTL 8.1 And 8.0</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">           @@ TODO</font></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Changes Between WTL 8.0 And 7.5"></a>Changes Between WTL 8.0 And 7.5</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">New and improved:</font></p>
+<blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">RunTimeHelper functions for 
+       correct struct sizes on different versions of Windows<br>ModuleHelper functions for uniform support of ATL3 and ATL7 module classes<br>SecureHelper functions for support of secure and non-secure run-time 
+       functions<br>Support for new Vista features:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Support for new messages for common controls, dialogs, etc.</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Support for TaskDialog</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">New Shell file dialogs (IFileOpenDialog and IFileSaveDialog)</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">New Aero Wizard support classes</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">New classes for Buffered Paint and Buffered Animation</font></p>
+               </li>
+       </ul>
+       <p style=margin:0in><font face="Arial" size="2">New TabView classes<br>New dialog class that uses in-memory dialog templates<br>New CMultiFileDialogImpl and CMultiFileDialog classes that support 
+       multi-select file dialogs<br>Added message cracker handler prototypes for all handlers<br>Replaced use of _alloca with CTempBuffer everywhere (and added CTempBuffer 
+       version for ATL3)<br>New classes for find/replace support for Edit or RichEdit<br>New class CFileDialogEx that supports GetOpenFileNameEx for Windows Mobile 5<br>
+       New features for the App Wizard:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">New default version values</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Unicode build option</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Support for TabView applications</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Support for Explorer applications</font></p>
+               </li>
+       </ul>
+       <p style=margin:0in><font face="Arial" size="2">Updates for the desktop App Wizard:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Added calls to set font for views based on controls that use font</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Added scroll window as another view type</font></p>
+               </li>
+       </ul>
+       <p style=margin:0in><font face="Arial" size="2">Support for VC2005 Express:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Setup for VS2005x</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Changes in default.js to take into account that VC2005x does not have a 
+       resource editor</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Generated code allows use of ATL3 from the Platform SDK</font></p>
+               </li>
+       </ul>
+       <p style=margin:0in><font face="Arial" size="2">New AppWizard for Mobile 2003 and 2005 platforms<br>
+       New samples:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Aero - demonstrates the 
+               Vista Glass UI</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">MiniPie - Windows Mobile 2005 PPC and Smartphone sample</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">TabBrowser - a web browser using TabView class</font></p>
+               </li>
+       </ul>
+       <p style=margin:0in><font face="Arial" size="2">MTPad sample updated to show usage of CRichEditFindReplaceImpl and 
+       CEditCommands/CRichEditComma</font></p>
+</blockquote>
+  <p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
+  <blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added support for menu items 
+       with bitmaps on Vista</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Keyboard cues shown 
+       even if the window is disabled</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CFolderDialog:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added support for PIDLs in 
+       addition to the file path</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Replaced use of SHGetMalloc 
+       with CoTaskMemFree</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">Scroll Windows:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CZoomScrollImpl - some 
+       methods should be overridable</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added support for 
+       WM_MOUSEHWHEEL in CScrollImpl</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">App Wizard:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: AppWizard fails to add 
+       files if C:\Temp does not exist</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard generates 
+       security warning when loaded</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard generates 
+       level 4 warning for modal dlg project</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard setupXX.js 
+       scripts silently fail on Vista</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Added code to 
+       unregister message filer and idle processing</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Added WS_CLIPSIBLINGS 
+       to dialog forms to avoid rebar drawing problems</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">App Wizard CE:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard CE should 
+       not have rich edit as a view option</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard CE generates 
+       level 4 warnings for single instance apps</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added support for Windows 
+       Mobile 6 SDKs</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">Cracked Handlers:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Corrected MSG_WM_TIMER 
+       and handler prototype, removed unused argument (breaking change)</font></p>
+       </li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: atlcrack.h does not 
+       support WTL namespace</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CDialogResize:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added SetIcon(NULL, FALSE) 
+       for CDialogResize to remove the generic icon for resizable dialogs</font></p>
+       </li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Enabled size/move for 
+       both X and Y</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added center flags for 
+       controls</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Const issue with title 
+       argument of AddSimpleReBarBand</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: DECLARE_FRAME_WND_CLASS 
+       definition missing WTL namespace</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">Windows CE:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Some symbols not 
+       defined for CE 4.0</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Incorrect WinCE 
+       exclusions</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Pocket PC - assert 
+       after navigating a CHyperLink</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Property sheet with 
+       listview on WM5.0 causes stack overflow</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CFindFile::GetFilePath() 
+       fails on diskless root requests</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: VS 2005 dialog editor 
+       bug - DS_FIXEDSYS used but not defined</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Windows Mobile 2005 
+       compatibility issues</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CFullScreenFrame on 
+       Smartphone 20003</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: SmartPhone back key 
+       handling in CAppWindow</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added orientation aware 
+       support to CAppStdDialogImpl</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added CAxDialogImpl base for 
+       CStdDialogImpl, CStdDialogResizeImpl and CStdOrientedDialogImpl</font></p>
+       </li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added various CStdDialogxxx 
+       enhancements</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CStdDialogBase does not 
+       scale dialog title on VGA</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: DIBINFO16 triggers code 
+       analysis warning</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added LPCTSTR 
+       AtlLoadString(UINT uID) - CE only overload</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added imaging draw support 
+       to CZoomScrollImpl</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added CBottomTabViewImpl and 
+       CBottomTabView classes for PPC</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CFindFile:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CFindFile class uses 
+       CRT functions</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: FindFile() uses lstrcpy 
+       without checking length</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">General:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Adding ReBar bands 
+       fails with new Windows SDK</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added support for relative 
+       include paths</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Using std::min and 
+       std::max</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Problems using WTL with 
+       MFC</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Improved support for Secure 
+       CRT</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Changed implementation of 
+       CSize, CPoint, CRect, and CString to be inside class definitions</font></p>
+       </li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">atltheme.h: Corrected method 
+       signatures for differences in uxtheme.h versions</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Replaced malloc/free with 
+       new/delete where appropriate</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CString::FormatV can 
+       cause GPF with Unicode strings</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">CHyperLink: Added handler 
+       for WM_SIZE</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CTheme needs 
+       constructor from HTHEME handle</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added Add* methods to 
+       several control classes in atlctrls.h to augment Insert* methods</font></p>
+       </li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Incorrect casting in 
+       CRichEditCtrl::GetLine()</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: 
+       CTreeViewCtrl::GetItemState changed to return only state-bits as specified 
+       by mask</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CBitmapButton::DoPaint 
+       - wrong button image</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Added another variant of 
+       CDCT::Drawtext with LPTSTR argument that allows text change</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: 
+       CRecentDocumentListBase::AddToList() uses lstrcpy</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: AtlLoadString(uID, 
+       lpBuffer, nBufferMax) has unnecessary code</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: CCursor::LoadOEMCursor 
+       asserts on IDC_HAND</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Memory leak when using 
+       CRT functions while printing</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">Fix: Undefined CString 
+       namespace</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">CPaneContainer: Added border 
+       styles</font></p></li>
+       <li>
+       <p style=margin:0in><font face="Arial" size="2">CSplitterImpl: Added 
+       SetSplitterPosPct, and changed App Wizard code to use it</font></p></li>
+       </ul>
+  </blockquote>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Changes Between WTL 7.5 And 7.1"></a>Changes Between WTL 7.5 And 7.1</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">New and improved:</font></p>
+<blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">VS2005 Compatibility: 
+       Added support for Visual Studio 2005 - both desktop and Windows CE<br>
+       Classes for icons, cursors, accelerator tables<br>
+       CSortListViewImpl, CSortListViewCtrlImpl, and CSortListViewCtrl classes<br>
+       Impl classes for Wizard 97 style wizards: CWizard97Sheet, 
+       CWizard97Page, CWizard97ExteriorPage, CWizard97InteriorPage<br>
+       CMemoryDC and CDoubleBufferWindowImpl classes<br>
+       Windows CE specific classes in new header, atlwince.h<br>
+       CScrollContainer class<br>
+       CZoomScrollImpl and CZoomScrollWindowImpl classes<br>
+       CZoomPrintPreviewWindowImpl and CZoomPrintPreviewWindow classes<br>
+       Global functions: AtlGetBitmapResourceInfo, 
+       AtlGetBitmapResourceBitsPerPixel<br>
+       New REFLECT_* macros to enable selective reflection of messages<br>
+       App Wizard: Added App Wizard for VS2005<br>
+       App Wizard: Added App Wizard for Windows CE for VS2005<br>
+       New samples: WTLExplorer, ImageView, SPControls<br>
+&nbsp;</font></p>
+</blockquote>
+  <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
+  <blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">DrawBitmapDisabled() 
+               doesn't work correctly on Longhorn</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Submenu size not correct if 
+       command bar is off-screen</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Added handler for 
+       WM_SETTINGCHANGE to improve theme color changes</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Better support for 
+       8/16/24-bit images</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Command Bar with 2 Levels of 
+       submenus remains active</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Hook procedure fails to call 
+       next hook</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">OnDestroy() should not 
+       decrement hook use if AttachToWindow() is used</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">MDI Command Bar:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Grows bigger if you 
+               switch between two maximized MDI child window types</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Move all hook messages 
+               processing to a separate function and use pT</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">MDI icon &amp; buttons should 
+       have themed background</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Should make MDI buttons gray 
+       when inactive<br>&nbsp;</font></p></li>
+       </ul>
+       <p style=margin:0in><font face="Arial" size="2">CString:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Helper functions not 
+               overloaded properly</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Some return types are 
+               'const CString&amp;' and could be just 'CString&amp;'</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">FormatV() passes size in 
+       characters to _alloca, should be in bytes</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Fixed stack corruption in 
+       FormatV()</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Improved boundaries checking 
+       for integer overflows/underflows<br>&nbsp;</font></p></li>
+       </ul>
+       <p style=margin:0in><font face="Arial" size="2">CScrollImpl:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Scroll bars problem when 
+               changing range</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">SetScrollOffset() doesn't 
+       move child windows</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Range and thumb drawing 
+       problems</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Possible overflow in 
+       OnMouseWheel()</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Support for 
+       SIF_DISABLENOSCROLL</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Added ScrollToView methods</font></p>
+               </li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CMapScrollImpl:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">SetScrollSize() incorrectly 
+       inverts xMin and xMax</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">SetScrollSize() uses bRedraw 
+       = NULL</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CTheme:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">GetThemeFont() bad parameter 
+       ordering</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Uses LOGFONT and TEXTMETRIC 
+       incorrectly (SDK header problem)</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Improved sizing for Windows 
+       CE</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CreateSimpleToolBarCtrl() 
+       should handle 24-bit bitmaps</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Changed WinCE 
+       CCECommandBarCtrl typedef and added a PPC CMenuBarCtrl</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">UpdatesBarPosition() doesn't 
+       take Windows CE command bar into account</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CDialogResize:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Enabled use for Windows CE</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Add WS_EX_DLGMODALFRAME to 
+       prevent empty icon</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CReBarCtrl:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Background not painted when 
+       resized</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Fixed typo in LockBands()</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">MaximizeBand needs BOOL 
+       fIdeal argument</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CRichEdit:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">GetSelText() should 
+               support UNICODE strings</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">GetSelText() uses lpstr instead of lpstrText</font></p></li>
+       </ul>
+  <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CHyperLink:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Added _xttoi() helper to 
+       avoid CRT in _ATL_MIN_CRT</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Fixed resource leak by 
+       destroying tooltip window<br>&nbsp;</font></p></li>
+       </ul>
+       <p style=margin:0in><font face="Arial" size="2">CPropertySheetImpl:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Improved support for Windows 
+       CE</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Sheet without title 
+       generates a memory fault on Windows CE</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CFolderDialog:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Add a way to set an initial 
+       folder</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Uses BFFM_IUNKNOWN which is 
+       not always defined</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">Update UI:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Add support to 
+               dynamically add UpdateUI elements</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">UIUpdateMenuBarElement() 
+               should use EnableMenu() instead of SetMenuItemInfo() for Windows CE</font></p>
+               </li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">CDC:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">FillSolidRect() should 
+               restore background color</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">GetClipRgn() method 
+               missing</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">Printing:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">
+               CPrinter::CreatePrinterDC() and CreatePrinterIC() members should be 
+               const</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CDevMode::CopyToHDEVMODE() is missing a call to GlobalUnlock()</font></p>
+               </li>
+       </ul>
+  <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">AppWizard:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Use WTL subfolder to 
+               create WTL category for VC7.x and VC8</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Rename files from 
+               WTLApp7x to WTLAppWiz, and add VS2005 setup file</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Fixed setup 
+               for x64</font></p></li>
+       </ul>
+  <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">General:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Redefinition of _MAX_FNAME 
+               with Dinkumware Standard C++ Library on Windows CE</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Added ATLVERIFY macro 
+               for ATL3</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Support warning level 4</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Missing methods 
+               CToolBarCtrl::SetButtonInfo, InsertButton, CTabCtrl::SetItem, 
+               CComboBoxEx::InsertItem, SetItem</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Missing support for 
+               WM_PRINTCLIENT</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Removed usage of IsBad* 
+               functions</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Fixed various compiler 
+               warnings</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">TCHAR bugs in various 
+               files</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">Improved Windows CE support and changes for Visual Studio 2005</font></p></li>
+       </ul>
+       <p style=margin:0in>&nbsp;</p>
+       <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
+       <ul style='margin-top:0in;margin-bottom:0in'>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CMDIChildWindowImpl: 
+               HMENU should be destroyed in OnDestroy()</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CStatic: Should use 
+               STM_SETIMAGE instead of STM_SETICON for SetIcon() on Windows CE</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CButton: GetButtonStyle() 
+               uses wrong mask</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CImageList: Made 
+               Duplicate() method const</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CListViewCtrl: Made 
+               SubItemHitTest() method const</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CTreeViewCtrl: GetItem() 
+               and SetItem() incorrectly restricted to _WIN32_IE &gt;= 0x0500</font></p>
+               </li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CMonthCalendarCtrl: 
+               GetMonthRange() should be GetMaxTodayWidth()</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CDateTimePickerCtrl: 
+               SetFormat() should have const argument</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CBitmapButtonImpl: Fixed 
+               resource leak by destroying tooltip window</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">
+               CMultiPaneStatusBarCtrlImpl: Cannot handle wide panes without resource 
+               strings</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CCheckListViewCtrlImpl: 
+               Call CheckSelectedItems() through pT</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CPaneContainerImpl: 
+               SetPaneContainerExtendedStyle() should use pT to call CalcSize()</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CFindFile: Enabled for 
+               Windows CE</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CPropertyPageImpl: Added 
+               handlers for callback messages</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">atlcrack.h: Added return 
+               value for MSG_WM_APPCOMMAND</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CMenu: New method variants: AppendMenu, InsterMenu, ModifyMenu</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CFont: Added arguments 
+               for bold and italic to CreatePointFont()</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CSize: Added scalar 
+               operators for WTL::CSize and ATL::CSize</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CRecentDocumentList: 
+               Allow changing the &quot;DocumentCount&quot; and &quot;Document%i&quot; registry values 
+               strings</font></p></li>
+               <li>
+               <p style=margin:0in><font face="Arial" size="2">CSplitterWindowImpl: 
+               Enabled use for Windows CE</font></p></li>
+       </ul>
+  </blockquote>
+<p style=margin:0in><br>
+&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Changes Between WTL 7.1 And 7.0"></a>Changes Between WTL 7.1 And 7.0</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">New and improved:</font></p>
+<blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">VC7 Compatibility: Support for 
+  ATL7 Module classes and critical sections and AppWizard setup for VC++ 7.1</font></p>
+  <p style=margin:0in><font face="Arial" size="2">Windows CE Support: Full 
+  compatibility with Windows CE platforms and AppWizard for eMbedded Visual C++</font></p>
+  <p style=margin:0in><font face="Arial" size="2">Namespace Support: Automatic 
+  &quot;using ATL&quot; (ATL7 only) or &quot;using WTL&quot; can now be turned off</font></p>
+  <p style=margin:0in><font face="Arial" size="2">CHyperLink New Features: not 
+  underlined, underlined when hover, command button, link tags</font></p>
+  <p style=margin:0in><font face="Arial" size="2">CCustomWaitCursor class 
+  supports custom and animated wait cursors</font></p>
+  <p style=margin:0in><font face="Arial" size="2">AtlCreateBoldFont() for 
+  creating bold version of an existing font</font></p>
+</blockquote>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
+  <blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CreateSimpleToolBarCtrl() - 
+  remove dead code, improve error checking, add a global function that uses it</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - PrepareChevronMenu() fails to 
+  get toolbar strings for Unicode</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CFrameWindowImplBase::Create() 
+  - improve ASSERT not to use m_hWnd if creation fails</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CFrameWndClassInfo::Register - 
+  should use %p formatting only for _WIN32_WINNT &gt;= 0x0500 or for _WIN64</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Chevron menus not positioned 
+  correctly with RTL</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CMDIChildWindowImpl: Problems 
+  creating maximized child windows and handling focus</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CMDIChildWindowImpl: Should 
+  activate on WM_MOUSEACTIVATE</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">UpdateUI:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Incorrectly clears default 
+  item from the system menu in MDI apps</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Added UISetCheck with bool 
+  instead of int for the check state</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">DDX:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Doesn't provide a way to 
+  change floating point precision</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Added DDX_CONTROL_HANDLE for 
+  non-CWindowImpl objects</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Added DDX_Check variant with 
+  bool instead of int for the check state</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - OnDrawItem() and OnMeasureItem() 
+  don't do a good check for owner-draw menu items</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Disabled 32-bit images not 
+  painted correctly in 3D menu mode</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Popup menus not positioned 
+  correctly with RTL</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Uses GCL_HICONSM instead of 
+  GCLP_HICONSM with GetClassLongPtr()</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">MDI Command Bar:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Doesn't refresh icon if MDI 
+  children are different</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">OnAllHookMessages() - improve 
+  code to handle MDI child window class icon</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - OnNcLButtonDown() uses 
+  TPM_VERPOSANIMATION without checking Windows version</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Maximized MDI buttons in wrong 
+  place for RTL</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Should adjust cxIdeal for 
+  rebar bands for IE4</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Add support for different 
+  top-level menu widths by handling ideal size for rebar bands</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">AppWizard:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Doesn't support MSDI 
+  application as a COM Server</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - MDI with Form View - stack 
+  overflow closing maximized MDI child windows</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Generates VERSION resource 
+  name 'test1' regardless of the project name</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Dialog project with control 
+  hosting doesn't derive a dialog from CAxDialogImpl</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - COM Server doesn't register 
+  type library</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - COM Server doesn't register 
+  AppID properly</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CTreeViewCtrl:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - GetItemData() needs better 
+  return value</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - GetItemState() should use 
+  TVM_GETITEMSTATE instead of TVM_GETITEM for IE5</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">GetItem() and SetItem() - 
+  added 
+  new variants that use TVITEMEX</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - SortChildren() should add 
+  recurse flag argument</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CTreeItem doesn't support 
+  CTreeViewCtrlExT that has different TBase than CWindow</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CThemeImpl:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Uses scalar delete instead of 
+  the vector one</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - EnableThemeDialogTexture() 
+  argument is BOOL instead of DWORD</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CFolderDialog:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - EnableOK() passes wrong 
+  arguments to BFFM_ENABLEOK</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Always clears m_hWnd, which 
+  causes problem for nested messages</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CDialogResize:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - DlgResize_Init() forces dialog 
+  to be visible by using SetRedraw()</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Forcing WS_THICKFRAME is not 
+  enough to make dialog resizable</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Min track size should be used 
+  for child dialogs as well</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - DlgResize_PositionControl() 
+  incorrectly checks return value from MapWindowPoints()</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CAppModule:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CAppModule methods not 
+  thread-safe</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - AddSettingChangeNotify() 
+  unusable in multithreaded apps because of delayed initialization</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CString:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Delete() doesn't allow 
+  deleting more than the length of the string</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Append() can cause buffer 
+  overrun</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - MakeReverse() can cause an 
+  infinite loop</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - _cstrstr() unnecessarily 
+  inefficient</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - FindOneOf() is not DBCS-aware</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Format() does not recognize %E</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - TrimLeft() and TrimRight() are 
+  only half-way DBCS-aware</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - May cause assertions or 
+  undefined behavior with SBCS</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CRecentDocumentList:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - SetMaxEntries() has an 
+  incorrect ASSERT</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Add CString variant of the 
+  GetFromList() method</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Add a way to replace command 
+  IDs used for the MRU list</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Add a way to replace registry 
+  key name</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CMessageLoop::Run() - improve 
+  the loop by checking bDoIdle before calling PeekMessage()</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CServerAppModule: Clean-up 
+  unused code</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CServerAppModule::MonitorProc() 
+  - no need to call _endthreadex()</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CListBox::GetText() and 
+  CComboBox::GetLBText() (CString variants) don't check for LBERR/CB_ERR</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CAxPropertyPageImpl doesn't 
+  create ActiveX controls with ATL7</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CDC::GetTextExtentExPoint() 
+  missing</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CDC::SetWindowExt() should 
+  have default value NULL for the lpSizeRet argument</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CPropertySheetWindow missing 
+  methods for PSM_INSERTPAGE, PSM_SETHEADERTITLE, and PSM_SETHEADERSUBTITLE; 
+  AddPage should return BOOL</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CMapScrollImpl::SetScrollSize() 
+  uses wrong variable</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CHyperLink: WM_UPDATEUISTATE 
+  causes repaint without WM_PAINT</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CUpDownCtrl::GetPos() returns 
+  incorrect value</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CUpDownCtrl::GetPos32() 
+  doesn't have default arg value</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CMultiPaneStatusBarCtrl: 
+  Always uses size grip for positioning panes</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CTabCtrl::InsertItem() should 
+  return int, not BOOL</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CReBarCtrl: Added LockBands() 
+  method</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CFont: uninitialized variable 
+  passed to DPtoLP</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CPrintDialogImpl: Crash when 
+  displaying Print Setup dialog</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix -
+  CPageSetupDialogImpl::PaintHookProc() - should use T* and return UINT_PTR 
+  instead of UINT</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CPrintJob doesn't support 
+  printing to a file</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CSplitterImpl: Doesn't handle 
+  WM_CAPTURECHANGED - can get in an invalid state</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CRichEditCtrl: Add method for 
+  EM_SETTABSTOPS</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - CFindFile::GetFilePath() 
+  checks for a trailing slash, but doesn't use that info</font></p>
+    </li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">General:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Problems compiling with /Zc:forScope 
+  ('for' loop scope conformance)</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Use named constants instead of 
+  values for pixel sizes, buffer lengths, etc.</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Support building with Managed 
+  C++ (/CLR)</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CMenuItemInfo - add run-time 
+  support for different versions of Windows</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">CommCtrl.h change - additional 
+  fields in IMAGELISTDRAWPARAMS now depend on _WIN32_IE instead of _WIN32_WINNT</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Incorrect usage of CRegKey::QueryStringValue()</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Operator = for GDI and USER 
+  wrappers leaks handle if it's managed variant</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - GDI and USER wrappers break 
+  under self-assignments</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Fix - Chaining messages with cracked 
+  handlers broken with ATL7</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Initialize all variables and 
+  structures prior to use</font></p>
+    </li>
+    <li>
+  <p style=margin:0in><font face="Arial" size="2">Use new common control struct 
+  names</font></p>
+    </li>
+  </ul>
+  </blockquote>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Changes Between WTL 7.0 And 3.1"></a>Changes Between WTL 7.0 And 3.1</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">New classes and features:</font></p>
+<blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">Support for new Common Controls v6 messages</font></p>
+  <p style=margin:0in><font face="Arial" size="2">Support for Visual Studio .NET and ATL 7.0</font></p>
+  <p style=margin:0in><font face="Arial" size="2">WTLApp70 - new AppWizard for Visual Studio 
+  .NET</font></p>
+  <p style=margin:0in><font face="Arial" size="2">CThemeImpl - implements support for Windows XP 
+  themes</font></p>
+  <p style=margin:0in><font face="Arial" size="2">CMDICommandBarCtrl - implements Command Bar for 
+  MDI applications</font></p>
+</blockquote>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
+<blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Bogus assert in OnDestroy</font></li>
+    <li><font face="Arial" size="2">Check marks can be truncated in large font 
+    settings</font></li>
+    <li><font face="Arial" size="2">Use pT to access GetSystemSettings, 
+    DrawMenuText, DrawBitmapDisabled, Draw3DCheckmark, DoPopupMenu, 
+    DoTrackPopupMenu, TakeFocus, GiveFocusBack, so they can be overridden</font></li>
+    <li><font face="Arial" size="2">No hot-tracking if main window is not active</font></li>
+    <li><font face="Arial" size="2">Top level items not painted inactive if app 
+    looses activation while drop down menu is displayed</font></li>
+    <li><font face="Arial" size="2">Added Windows XP flat menus support</font></li>
+    <li><font face="Arial" size="2">Drop-down menu doesn't close if clicked 
+    again (Windows XP only)</font></li>
+    <li><font face="Arial" size="2">Menu item text and accelerator text too 
+    close with some settings</font></li>
+    <li><font face="Arial" size="2">Keyboard can still access clipped menu items</font></li>
+    <li><font face="Arial" size="2">Added support for hiding keyboard navigation 
+    indicators until Alt key is pressed (system setting)</font></li>
+    <li><font face="Arial" size="2">Added AddIcon and ReplaceIcon variants for 
+    icon resources</font></li>
+    <li><font face="Arial" size="2">Image size calculated differently in 
+    different places</font></li>
+    <li><font face="Arial" size="2">Add support for 32-bit (alpha channel) 
+    bitmaps for Windows XP</font></li>
+    <li><font face="Arial" size="2">Fixed width calculation for default menu 
+    items</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">AddSimpleReBarBandCtrl sets toolbar extended 
+    styles without preserving old ones</font></li>
+    <li><font face="Arial" size="2">PrepareChevronMenu should not create menu 
+    items for buttons with TBSTATE_HIDDEN</font></li>
+    <li><font face="Arial" size="2">TPM_VERPOSANIMATION will not be defined in 
+    atlframe.h if atlctrlw.h is included first</font></li>
+    <li><font face="Arial" size="2">CreateSimpleToolBarCtrl - height might be 
+    too small if large font is used</font></li>
+    <li><font face="Arial" size="2">PrepareChevronMenu uses TB_GETBUTTONTEXT, 
+    better use TB_GETBUTTONINFO</font></li>
+    <li><font face="Arial" size="2">Chevron menu doesn't close if clicked again 
+    (Windows XP only)</font></li>
+    <li><font face="Arial" size="2">Should check local classes for superclassing</font></li>
+    <li><font face="Arial" size="2">Add support for 32-bit (alpha channel) 
+    bitmaps for Windows XP</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Update UI:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">UISetText can clear other menu item flags</font></li>
+    <li><font face="Arial" size="2">CUpdateUI::UIUpdateState assigns value with 
+    |= instead of =</font></li>
+    <li><font face="Arial" size="2">Added UISetDefault() and fix default state 
+    to work with menus</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CString:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">GetBuffer() and GetBufferSetLength() should 
+    return NULL in out-of-memory condition</font></li>
+    <li><font face="Arial" size="2">Added missing methods: separate c-tors for 
+    LPCSTR and LPCWSTR, CollateNoCase, TrimRight and TrimLeft variants, Find 
+    variants, moved FormatV to public</font></li>
+    <li><font face="Arial" size="2">Fix _IsValidString usage</font></li>
+    <li><font face="Arial" size="2">FormatV incorrectly calculates buffer size 
+    (too big)</font></li>
+    <li><font face="Arial" size="2">Usage of _ttoi causes problems with _ATL_MIN_CRT 
+    in VC7</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CDC:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">GetTabbedTextExtent() should return DWORD 
+    instead of BOOL</font></li>
+    <li><font face="Arial" size="2">Add FillRect() that accept color index 
+    instead of a brush handle</font></li>
+    <li><font face="Arial" size="2">DrawDragRect() leaks regions and a brush</font></li>
+    <li><font face="Arial" size="2">Improved DitherBlt() - added brushes as 
+    arguments for used colors</font></li>
+    <li><font face="Arial" size="2">Added DrawShadowText() (uses LoadLibrary/GetProcAddress 
+    to run on older Windows)</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CListViewCtrl:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">SetItemState should use LVM_SETITEMSTATE</font></li>
+    <li><font face="Arial" size="2">SetItemCount should return a BOOL</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CRichEditCtrl:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Added SetCharFormat() variant that accepts 
+    flags (for SCF_ALL)</font></li>
+    <li><font face="Arial" size="2">CharFromPos() should pass a pointer to 
+    POINTL in lParam</font></li>
+    <li><font face="Arial" size="2">GetTextRange() - should add Unicode variant 
+    for rich edit version &gt;= 2</font></li>
+    <li><font face="Arial" size="2">Added another FormatRange() that can accept 
+    a pointer to FORMATRANGE (needed for passing NULL to clear cache)</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CHyperLink:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Allow overriding of Navigate and 
+    CalcLabelRect</font></li>
+    <li><font face="Arial" size="2">Doesn't handle right or center alignment</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CColorDialog:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Has static variables that were not 
+    initialized with _ATL_MIN_CRT</font></li>
+    <li><font face="Arial" size="2">Fixed HookProc for ColorOK message - the 
+    message is not sent, but the hook proc is called directly</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">atlcrack.h:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">MSG_WM_TIMER crack macro should cast to 
+    TIMERPROC instead of TIMERPROC*</font></li>
+    <li><font face="Arial" size="2">Add cracked handlers for all new messages in 
+    Common Controls 6</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">atlapp.h:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Fixed problems with atlTraceUI with ATL7</font></li>
+    <li><font face="Arial" size="2">#ifdefs for ATL7 were in the wrong place</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">atlctrls.h:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Add support in control classes for all new 
+    messages in Common Controls 6</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CRecentDocumentList:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">AtlCompactPath corrupts memory if filename 
+    is longer than requested compact size</font></li>
+    <li><font face="Arial" size="2">ReadFromRegistry incorrectly checks for 
+    error when reading from registry</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CSplitterWindow:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Incorrect calculation of middle position</font></li>
+    <li><font face="Arial" size="2">3D border now drawn only if WS_EX_CLIENTEDGE 
+    is set</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Printing:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Uses DWORD instead of an int for a job ID</font></li>
+    <li><font face="Arial" size="2">CPrintJob::CancelPrintJob shouldn't have a 
+    return value</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">CRegKey::QueryValue and SetValue are 
+    deprecated in ATL7</font></li>
+    <li><font face="Arial" size="2">Added direct support for ATL7</font></li>
+    <li><font face="Arial" size="2">Replace ScreenToClient and ClientToScreen 
+    with MapWindowPoints to support RTL layout</font></li>
+    <li><font face="Arial" size="2">CFindFile::GetFilePath(LPTSTR...) returns 
+    path without the file name</font></li>
+    <li><font face="Arial" size="2">MDI: Updating client edge in 
+    WM_WINDOWPOSCHANGING causes minimize/maximize/restore animation problems, 
+    use WM_WINDOWPOSCHANGED</font></li>
+    <li><font face="Arial" size="2">Custom Draw: Added 
+    CCustomDraw::OnSubItemPrePaint() overrideable method</font></li>
+    <li><font face="Arial" size="2">CFolderDialogImpl uses 'this' for 
+    BROWSEINFO.lParam instead of T*</font></li>
+    <li><font face="Arial" size="2">CImageList::Destroy shouldn't use Detach()</font></li>
+    <li><font face="Arial" size="2">ATL7 has its own AtlLoadString</font></li>
+    <li><font face="Arial" size="2">CPropertySheet doesn't close when you press 
+    X button</font></li>
+    <li><font face="Arial" size="2">Fixed problems for _U_STRINGorID and others 
+    that moved from atlbase.h to atlwin.h in ATL7</font></li>
+    <li><font face="Arial" size="2">Add AtlMessageBox() that accepts either 
+    in-memory or resource strings</font></li>
+    <li><font face="Arial" size="2">CScrollImpl: fixed bug with scrolling child 
+    windows</font></li>
+    <li><font face="Arial" size="2">CPropertyPageImpl: Add new notification 
+    handlers to enable direct return values (use #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS 
+    to use them)</font></li>
+    <li><font face="Arial" size="2">Add AtlInitCommonControls() to simplify use</font></li>
+    <li><font face="Arial" size="2">DDX: Fixed usage of the size of char arrays 
+    for DDX</font></li>
+    <li><font face="Arial" size="2">CPageSetupDialog: changed usage of 
+    CWndProcThunk because of changes in ATL7</font></li>
+    <li><font face="Arial" size="2">Fix confusing precedence in expressions</font></li>
+    <li><font face="Arial" size="2">Removed forward declarations because default 
+    values for template arguments shouldn't be specified in two places (we don't 
+    need them anyway)</font></li>
+    <li><font face="Arial" size="2">Win64: Fix /Wp64 warnings from 32-bit VC7 
+    compiler caused by SDK headers</font></li>
+    <li><font face="Arial" size="2">Fix direct usage of English strings (they 
+    can be #defined to something else now)</font></li>
+    <li><font face="Arial" size="2">AtlGetCommCtrlVersion not defined if _ATL_DLL 
+    is in ATL 3.0 (and CmdBar is using it)</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">AppWizard:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Added manifest for Common Controls 6</font></li>
+    <li><font face="Arial" size="2">Loading Rich Edit DLL should use HMODULE</font></li>
+    <li><font face="Arial" size="2">Should not use atlimpl.cpp for ATL7</font></li>
+    <li><font face="Arial" size="2">Added message handler prototypes to 
+    generated files</font></li>
+    <li><font face="Arial" size="2">VERSION resource always has VALUE &quot;OLESelfRegister&quot; 
+    (now only for COM servers)</font></li>
+    <li><font face="Arial" size="2">Added option for putting implementation in 
+    CPP files</font></li>
+    <li><font face="Arial" size="2">d-tor for the thread manager class in MSDI 
+    project executed after the heap is destroyed</font></li>
+    <li><font face="Arial" size="2">Wrong settings when changing to a dialog 
+    project and back (AppWizard 6.0 only)</font></li>
+    <li><font face="Arial" size="2">Remove cut/copy/paste accelerators for form 
+    view and dialogs projects</font></li>
+    <li><font face="Arial" size="2">Fix toolbar bitmaps so they are not 
+    transparent (problem with Windows XP flat menus only)</font></li>
+    <li><font face="Arial" size="2">Used CMDICommandBarCtrl for MDI apps</font></li>
+    <li><font face="Arial" size="2">Add symbols required for VC7 Class Wizard to 
+    recognize an ATL project</font></li>
+    <li><font face="Arial" size="2">Changed default styles for the rebar, so it 
+    does look OK without CmdBar and with manifest</font></li>
+    <li><font face="Arial" size="2">Added setup programs for both AppWizards</font></li>
+    <li><font face="Arial" size="2">Remove ignored resource attributes: 
+    MOVEABLE, PURE, etc. (AppWizard 7.0 only)</font></li>
+    <li><font face="Arial" size="2">Add call to DefWindowProc to WinMain to 
+    resolve possible problems if MSLU is used</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Samples:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Updated toolbar bitmaps, added #ifdefs for 
+    ATL7, added manifest file for CommCtrl6, qualified _U_RECT with WTL 
+    namespace, updated use of deprecated CRegKey functions, added VC7 projects</font></li>
+    <li><font face="Arial" size="2">Added Alpha sample</font></li>
+  </ul>
+</blockquote>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><b><font face="Arial">
+<a name="Changes Between WTL 3.1 And 3.0"></a>Changes Between WTL 3.1 And 
+3.0</font></b></p>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">New classes:</font></p>
+<blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">CPaneContainer - implements a window that 
+  provides a title bar and a close button (like Explorer)</font></p>
+  <p style=margin:0in><font face="Arial" size="2">CDialogResize - an MI class that allows 
+  resizing of dialogs (or any windows with child windows/controls)</font></p>
+  <p style=margin:0in><font face="Arial" size="2">CAxPropertyPageImpl - implements a property 
+  page that can host ActiveX controls</font></p>
+</blockquote>
+<p style=margin:0in>&nbsp;</p>
+<p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
+<blockquote style='margin-top:0in;margin-bottom:0in'>
+  <p style=margin:0in><font face="Arial" size="2">CServerAppModule now clears m_hEventShutdown to 
+  avoid calling CloseHandle twice</font></p>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CString:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">operator += now leaves original string 
+    intact if it's out of memory</font></li>
+    <li><font face="Arial" size="2">Fixed bad DWORD_PTR usage in TrimRight, 
+    TrimLeft, Replace, Remove</font></li>
+    <li><font face="Arial" size="2">Removed dependencies on CRT for projects 
+    that don't use it</font></li>
+    <li><font face="Arial" size="2">Insert - fixed string corruption in release 
+    builds</font></li>
+    <li><font face="Arial" size="2">Added optional floating point formatting 
+    (for projects that use CRT)</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CEdit and CRichEditCtrl: SetSelAll and 
+  SetSelNone had reversed implementation</font></p>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">atlres.h: Changed IDs so that they are 
+  compatible with MFC's afxres.h</font></p>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Added LoadMappedImages()</font></li>
+    <li><font face="Arial" size="2">Changed handling of left and right arrow 
+    keys so that they don't close context menus</font></li>
+    <li><font face="Arial" size="2">Add code to handle left/right arrow keys 
+    correctly on mirrored (RTL) systems</font></li>
+    <li><font face="Arial" size="2">Removed handler that eats parent window's 
+    WM_SETTINGCHANGE</font></li>
+    <li><font face="Arial" size="2">Fixed bitmap resource leak in 
+    Draw3DCheckmark</font></li>
+    <li><font face="Arial" size="2">Fixed incorrect usage of CharLower in 
+    OnMenuChar</font></li>
+    <li><font face="Arial" size="2">Fixed wrong color for the disabled items in 
+    hi-contrast mode</font></li>
+    <li><font face="Arial" size="2">Added code to gray menu items if main window 
+    is inactive</font></li>
+    <li><font face="Arial" size="2">Fixed keyboard mnemonic handling for IE 4</font></li>
+    <li><font face="Arial" size="2">Fixed hook problems with multiple cmdbars in 
+    the same thread</font></li>
+    <li><font face="Arial" size="2">Added support for radio menu items</font></li>
+    <li><font face="Arial" size="2">Added support for disabled top-level menu 
+    items (also added in CFrameWindowImpl::PrepareChevronMenu)</font></li>
+    <li><font face="Arial" size="2">Added keyboard shortcut (Alt+/) to invoke 
+    chevron menu</font></li>
+    <li><font face="Arial" size="2">Added support to override menu item length 
+    in a derived class</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CBitmapButton:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Bypassed BUTTON DefWindowProc for hover 
+    style so that the button doesn't take focus</font></li>
+    <li><font face="Arial" size="2">Added BMPBTN_AUTOFIRE extended style</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CDC:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Added _WTL_FORWARD_DECLARE_CSTRING define to 
+    allow usage of methods that accept CString</font></li>
+    <li><font face="Arial" size="2">Fixed errors in GetTextFace and 
+    GetMenuItemString</font></li>
+    <li><font face="Arial" size="2">Added GetCharWidth32</font></li>
+    <li><font face="Arial" size="2">Added DrawIconEx method</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CMenu:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Implement following missing methods:<br>
+&nbsp;&nbsp;&nbsp; GetMenuDefaultItem<br>
+&nbsp;&nbsp;&nbsp; GetMenuInfo<br>
+&nbsp;&nbsp;&nbsp; GetMenuItemRect<br>
+&nbsp;&nbsp;&nbsp; HiliteMenuItem<br>
+&nbsp;&nbsp;&nbsp; IsMenu<br>
+&nbsp;&nbsp;&nbsp; MenuItemFromPoint<br>
+&nbsp;&nbsp;&nbsp; SetMenuDefaultItem<br>
+&nbsp;&nbsp;&nbsp; SetMenuInfo</font></li>
+    <li><font face="Arial" size="2">GetMenuString - fixed to include space for 
+    terminating NULL character in returning string</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">GDI and USER classes should destroy the 
+  GDI/USER objects in Attach if GDI/USER resource is managed</font></p>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">OnToolTipText shouldn't save tool tip text 
+    if it's not for a menu</font></li>
+    <li><font face="Arial" size="2">AddSimpleReBarBandCtrl now adds chevron 
+    style only for toolbars with buttons</font></li>
+    <li><font face="Arial" size="2">AddSimpleReBarBand(Ctrl) - calc band ID if 
+    not specified</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CRecentDocumentList:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Fix - UpdateMenu deletes wrong menu item 
+    when the list is empty</font></li>
+    <li><font face="Arial" size="2">Added code to allow restricting the number 
+    of characters displayed by MRU menu items</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Update UI:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Added support for blocking accelerators for 
+    disabled items</font></li>
+    <li><font face="Arial" size="2">Improved search code assuming there are no 
+    duplicate entries (and added checks for duplicates)</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">CSplitterWindow:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">CSplitterWindowImpl should derive from 
+    CSplitterImpl&lt;T , t_bVertical&gt; to allow overriding of methods</font></li>
+    <li><font face="Arial" size="2">Added single pane mode and SetSinglePaneMode/GetSinglePaneMode</font></li>
+    <li><font face="Arial" size="2">Added right/bottom aligned resize mode using 
+    extended styles SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">atlcrack.h: Added handlers for following new 
+  messages:<br>
+&nbsp;&nbsp;&nbsp; WM_APPCOMMAND<br>
+&nbsp;&nbsp;&nbsp; WM_NCXBUTTONDOWN<br>
+&nbsp;&nbsp;&nbsp; WM_NCXBUTTONUP<br>
+&nbsp;&nbsp;&nbsp; WM_NCXBUTTONDBLCLK<br>
+&nbsp;&nbsp;&nbsp; WM_XBUTTONDOWN<br>
+&nbsp;&nbsp;&nbsp; WM_XBUTTONUP<br>
+&nbsp;&nbsp;&nbsp; WM_XBUTTONDBLCLK</font></p>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Win64:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Dialog return value should use 
+    DWLP_MSGRESULT and SetWindowLongPtr</font></li>
+    <li><font face="Arial" size="2">CMenu::InsertMenu, AppendMenu, ModifyMenu 
+    should have UINT_PTR for the menu ID</font></li>
+    <li><font face="Arial" size="2">Added appropriate type casts</font></li>
+    <li><font face="Arial" size="2">CFrameWindowImpl::m_szAutoName - changed the 
+    size to fit the pointer value size</font></li>
+    <li><font face="Arial" size="2">CListViewCtrl::SortItems should use LPARAM 
+    for user data instead of DWORD</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">Added optional mask argument to all methods 
+    for setting extended styles</font></li>
+    <li><font face="Arial" size="2">CMDIWindow::MDIRestore - fixed to send 
+    WM_MDIRESTORE instead of WM_MDIICONARRANGE</font></li>
+    <li><font face="Arial" size="2">CListViewCtrl: Added SortItemsEx method</font></li>
+    <li><font face="Arial" size="2">CToolBarCtrl::GetButtonInfo - fixed to 
+    return int instead of BOOL</font></li>
+    <li><font face="Arial" size="2">Added CToolBarCtrl::SetButtonSize and 
+    SetBitmapSize that accept cx and cy instead of SIZE</font></li>
+    <li><font face="Arial" size="2">Printing: Changed how GetNewDevModeForPage 
+    works (comments in code)</font></li>
+    <li><font face="Arial" size="2">CFileDialogImpl::_OnTypeChange incorrectly 
+    calls pT-&gt;OnSelChange instead of pT-&gt;OnTypeChange</font></li>
+    <li><font face="Arial" size="2">CMultiPaneStatusBarCtrl::GetPaneTipText - 
+    fixed to use index instead of and ID internally</font></li>
+    <li><font face="Arial" size="2">CWinDataExchange: Added references to 
+    arguments of DoDataExchange, so there are no level 4 warning even if the map 
+    is empty</font></li>
+    <li><font face="Arial" size="2">CPropertySheetWindow: Added new, IE 5.0 
+    specific methods</font></li>
+    <li><font face="Arial" size="2">CPropertyPageImpl: Added new, IE 5.0 
+    specific methods</font></li>
+  </ul>
+  <p style=margin:0in>&nbsp;</p>
+  <p style=margin:0in><font face="Arial" size="2">AppWizard:</font></p>
+  <ul style='margin-top:0in;margin-bottom:0in'>
+    <li><font face="Arial" size="2">added calls to RemoveMessageFilter and 
+    RemoveIdleHandler in CMainFrame::OnDestroy for COM server projects</font></li>
+    <li><font face="Arial" size="2">added scroll bars for HTML view</font></li>
+    <li><font face="Arial" size="2">CAppServerModule now handles -embedding as 
+    well as -automation</font></li>
+    <li><font face="Arial" size="2">corrected code in CMainFrame::OnShowToolBar 
+    to correctly identify the toolbar in a rebar</font></li>
+    <li><font face="Arial" size="2">dialog based app code now derives from 
+    CUpdateUI as public</font></li>
+  </ul>
+</blockquote>
+<p style=margin:0in>&nbsp;</p>
+
+<p style=margin:0in><font face="Arial" size="2">- end of readme.htm -</font></p>
+
+</body>
+
+</html>
\ No newline at end of file
index 0aeb97e..08158be 100644 (file)
Binary files a/nlite.suo and b/nlite.suo differ
index 2ffab18..b21e8df 100644 (file)
@@ -51,7 +51,7 @@
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <LinkIncremental>true</LinkIncremental>
-    <IncludePath>$(solutiondir)\nlib;$(solutiondir)\memorypool;$(solutiondir);$(solutiondir)\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(solutiondir)\nlib;$(solutiondir)\include\WTL\include;$(solutiondir);$(solutiondir)\include;$(IncludePath)</IncludePath>
     <EmbedManifest>false</EmbedManifest>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug-window|Win32'">
index f7eb898..29e92fa 100644 (file)
@@ -98,13 +98,14 @@ VOID CNicoLiveStream::DisConnect(){
        NicoLiveStream_disConnect(nicoLiveStream);
 }
 
-
+/*
 NLIB_RESULT CNicoLiveStream::SendChat(LPCTSTR chatBuf,std::vector<LPCTSTR> mails,std::vector<LPCTSTR> extends){
 
        return NicoLiveStream_sendChat(nicoLiveStream,chatBuf,&mails[0],&extends[0]);
 
 
 }
+*/
 
 }
 
index 62f12ef..ecafad3 100644 (file)
@@ -61,7 +61,7 @@ namespace nlite{
                
                VOID DisConnect();
 
-               NLIB_RESULT SendChat(LPCTSTR chatBuf,std::vector<LPCTSTR> mails,std::vector<LPCTSTR> extends);
+               //NLIB_RESULT SendChat(LPCTSTR chatBuf,std::vector<LPCTSTR> mails,std::vector<LPCTSTR> extends);
                
 
        };