diff options
author | Stef Walter <stef@thewalter.net> | 2003-09-20 07:12:49 +0000 |
---|---|---|
committer | Stef Walter <stef@thewalter.net> | 2003-09-20 07:12:49 +0000 |
commit | b49d8ebefe9b10c53a6a09ad564e22111b7b25c6 (patch) | |
tree | 1d5dd4abc38170a7bc106dabbc59b915017222f0 /win32/common | |
parent | 1cda9ebbd62916c7c2136722597a86c583e1ecf6 (diff) |
Initial Import
Diffstat (limited to 'win32/common')
-rw-r--r-- | win32/common/Makefile.am | 2 | ||||
-rw-r--r-- | win32/common/atlprsht.h | 915 | ||||
-rw-r--r-- | win32/common/atlwinhk.h | 151 | ||||
-rw-r--r-- | win32/common/droplet.cpp | 226 | ||||
-rw-r--r-- | win32/common/droplet.h | 98 | ||||
-rw-r--r-- | win32/common/errutil.cpp | 106 | ||||
-rw-r--r-- | win32/common/errutil.h | 32 | ||||
-rw-r--r-- | win32/common/mystring.h | 536 | ||||
-rw-r--r-- | win32/common/rep.ico | bin | 0 -> 766 bytes | |||
-rw-r--r-- | win32/common/rliberr.h | 136 | ||||
-rw-r--r-- | win32/common/rliberr.mc | 106 |
11 files changed, 2308 insertions, 0 deletions
diff --git a/win32/common/Makefile.am b/win32/common/Makefile.am new file mode 100644 index 0000000..e247bdb --- /dev/null +++ b/win32/common/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = atlprsht.h atlwinhk.h droplet.cpp droplet.h errutil.cpp errutil.h mystring.h rep.ico rliberr.mc + diff --git a/win32/common/atlprsht.h b/win32/common/atlprsht.h new file mode 100644 index 0000000..e5181ea --- /dev/null +++ b/win32/common/atlprsht.h @@ -0,0 +1,915 @@ +/* + * AUTHOR + * N. Nielsen + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + +// PropertyPage.h: interface for the CPropertyPage class. +// Implements Property Pages and Sheets for ATL +// By Stef 06/10/99 +// +// This class uses an MFC type Interface (CPropertySheet, CPropertyPage) +// the only difference being that many of the virtual notify functions +// are left for you to define in your derived classes using your message map +// +// Notes for CPropertySheet: +// 1. If you define a WM_INITDIALOG handler in your derived class make +// sure to either call the base handler (OnInitDialog) or set +// bHandled to false. +// +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_PROPERTYPAGE_H__1508DAF4_7AD1_11D3_BF96_0020182B97FC__INCLUDED_) +#define AFX_PROPERTYPAGE_H__1508DAF4_7AD1_11D3_BF96_0020182B97FC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#include <atlwin.h> +#include <atlwinhk.h> +#include <commctrl.h> + + +// 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 AFX_IDC_TAB_CONTROL 0x3020 + +// determine number of elements in an array (not bytes) +#define _countof(array) (sizeof(array)/sizeof(array[0])) + +template <class TBase> class CPropertySheetT; +template <class TBase> class CPropertyPageT; + +const int _PropSheetIDs[] = + { ID_WIZNEXT, ID_WIZFINISH, ID_WIZBACK, IDCANCEL }; +const int _PropSheetButtons[] = + { IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP }; + +//////////////////////////////////////////////////////////////////////// +// Implements one page of a Property Sheet +template <class TBase = CWindow> +class CPropertyPageT : public CDialogImplBaseT< TBase > +{ +// Construction +public: + CPropertyPageT(UINT IDD) : m_szCaption(NULL) + { Construct(IDD, _T("")); } + + // Caption from Resource + CPropertyPageT(UINT IDD, UINT nIDCaption) : m_szCaption(NULL) + { Construct(IDD, nIDCaption); } + + CPropertyPageT(UINT IDD, LPCTSTR szCaption) : m_szCaption(NULL) + { Construct(IDD, szCaption); } + + void Construct(UINT IDD, LPCTSTR szCaption) + { CommonConstruct(IDD, szCaption); } + + void Construct(UINT IDD, UINT nIDCaption) + { + ATLASSERT(nIDCaption != 0); + USES_CONVERSION; + CComBSTR bsCaption; + bsCaption.LoadString(nIDCaption); + CommonConstruct(IDD, OLE2T(bsCaption)); + } + + // All Construction ends up here + void CommonConstruct(UINT IDD, LPCTSTR szCaption); + + ~CPropertyPageT() + { if(m_szCaption) delete[] m_szCaption; } + +// Operations + void CancelToClose(); + void SetModified(bool bChanged); + void SetHelp(bool bHelp); + LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam); + bool IsButtonEnabled(int iButton); + void EndDialog(int nID); + +// Status + CPropertySheetT<TBase>* GetParentSheet(); + +// Implementaition +protected: + CPropertySheetT<TBase>* m_pSheet; // Pointer to Sheet + static UINT CALLBACK PropPageCallback(HWND hwnd, UINT uMsg, + LPPROPSHEETPAGE ppsp); + +// Data +public: + PROPSHEETPAGE m_psp; // API Structure + LPTSTR m_szCaption; // Caption + + friend class CPropertySheetT<TBase>; +}; + +// Common Construction +template <class TBase> +void CPropertyPageT<TBase>::CommonConstruct(UINT IDD, LPCTSTR szCaption) +{ + // Clear + memset(&m_psp, 0, sizeof(m_psp)); + + m_psp.dwSize = sizeof(m_psp); + m_psp.hInstance = _Module.m_hInstResource; + m_psp.pszTemplate = MAKEINTRESOURCE(IDD); + // Set to DialogProc + m_psp.pfnDlgProc = (DLGPROC)StartDialogProc; + // Use to hook up to ATL WndProc + m_psp.pfnCallback = PropPageCallback; + m_psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK; + // Passed to PropPageCallback + m_psp.lParam = (LPARAM)this; + + // Allocate String + if(m_szCaption && _tcslen(m_szCaption) < _tcslen(szCaption)) + { + delete[] m_szCaption; + m_szCaption = NULL; + } + + if(!m_szCaption) + m_szCaption = new TCHAR[_tcslen(szCaption) + 1]; + + _tcscpy(m_szCaption, szCaption); + m_psp.pszTitle = m_szCaption; + + // Set by CPropertySheetT::AddPage + m_pSheet = NULL; + +} + +// Callback used during actual creation of page +template <class TBase> +UINT CALLBACK CPropertyPageT<TBase>::PropPageCallback(HWND hwnd, UINT uMsg, + LPPROPSHEETPAGE ppsp) +{ + switch (uMsg) + { + case PSPCB_CREATE: + { + // Get ready for hooking up to an ATL WndProc + CPropertyPageT<TBase>* pPage = + (CPropertyPageT<TBase>*)ppsp->lParam; + _Module.AddCreateWndData(&(pPage->m_thunk.cd), pPage); + + return TRUE; + } + case PSPCB_RELEASE: + break; + } + + return 0; +} + +// Thin Wrapper +template <class TBase> +void CPropertyPageT<TBase>::CancelToClose() +{ + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + + ::SendMessage(GetParent(), PSM_CANCELTOCLOSE, NULL, NULL); +} + +// Thin Wrapper +template <class TBase> +void CPropertyPageT<TBase>::SetModified(bool bChanged) +{ + ATLASSERT(m_hWnd != NULL); + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + + if (bChanged) + ::SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, NULL); + else + ::SendMessage(GetParent(), PSM_UNCHANGED, (WPARAM)m_hWnd, NULL); +} + +// Thin Wrapper +template <class TBase> +LRESULT CPropertyPageT<TBase>::QuerySiblings(WPARAM wParam, LPARAM lParam) +{ + ATLASSERT(::IsWindow(m_hWnd)); + ATLASSERT(GetParent() != NULL); + + return ::SendMessage(GetParent(), PSM_QUERYSIBLINGS, wParam, lParam); +} + +template <class TBase> +void CPropertyPageT<TBase>::SetHelp(bool bHelp) +{ + if(bHelp) + m_psp.dwFlags |= PSP_HASHELP; + else + m_psp.dwFlags &= ~(PSP_HASHELP); +} + +// Thin wrapper +template <class TBase> +bool CPropertyPageT<TBase>::IsButtonEnabled(int iButton) +{ + HWND hWnd = ::GetDlgItem(::GetParent(m_hWnd), iButton); + if (hWnd == NULL) + return false; + return ::IsWindowEnabled(hWnd) ? true : false; +} + +// Routes EndDialog calls to the Sheet +template <class TBase> +void CPropertyPageT<TBase>::EndDialog(int nID) +{ + // Normally you shouldn't call EndDialog from a page. But in case it does + // happen during error situations, call CPropertySheetT::EndDialog instead. + CPropertySheetT<TBase>* pParent = GetParentSheet(); + if (pParent != NULL) + pParent->EndDialog(nID); +} + +// Return Sheet Pointer (which is initialized in CPropertySheetT::AddPage) +template <class TBase> +CPropertySheetT<TBase>* CPropertyPageT<TBase>::GetParentSheet() + { ATLASSERT(m_pSheet != NULL); return m_pSheet; } + + + + + +//////////////////////////////////////////////////////////////////////// +// Implements and hooks into Actual Property Sheet Window +template <class TBase = CWindow> +class CPropertySheetT : public CWindowImplBaseT< TBase > +{ +// Construction +public: + CPropertySheetT() : m_szCaption(NULL) + { CommonConstruct(_T(""), 0); } + + // Caption from Resource + CPropertySheetT(UINT nIDCaption, HWND hwndParent = NULL, UINT iSelectPage = 0) + : m_szCaption(NULL) + { Construct(nIDCaption, hwndParent, iSelectPage); } + + CPropertySheetT(LPCTSTR pszCaption, HWND hwndParent = NULL, UINT iSelectPage = 0) + : m_szCaption(NULL) + { Construct(pszCaption, hwndParent, iSelectPage); } + + // Caption from Resource + void Construct(UINT nIDCaption, HWND hwndParent = NULL, UINT iSelectPage = 0) + { + ATLASSERT(nIDCaption != 0); + USES_CONVERSION; + CComBSTR bsCaption; + bsCaption.LoadString(nIDCaption); + CommonConstruct(OLE2T(bsCaption), hwndParent, iSelectPage); + } + + void Construct(LPCTSTR pszCaption, HWND hwndParent = NULL, UINT iSelectPage = 0) + { CommonConstruct(pszCaption, hwndParent, iSelectPage); } + + // All actual initialization takes place here + void CommonConstruct(LPCTSTR sCaption, HWND hwndParent = NULL, UINT iSelectPage = 0); + + virtual ~CPropertySheetT() + { if(m_szCaption) delete[] m_szCaption; } + +// Creation +public: + // for modeless creation + // the default style, expressed by passing -1 as dwStyle, is actually: + // WS_SYSMENU | WS_POPUP | WS_CAPTION | DS_MODALFRAME | WS_VISIBLE + bool Create(HWND hwndParent = NULL, DWORD dwStyle = (DWORD)-1, DWORD dwExStyle = 0); + int DoModal(HWND hwndParent = NULL, DWORD dwStyle = (DWORD)-1, DWORD dwExStyle = 0); + +// Operations +public: + void AddPage(CPropertyPageT<TBase>* pPage); + void RemovePage(CPropertyPageT<TBase>* pPage); + void RemovePage(int nPage); + void EndDialog(int nEndID); // used to terminate a modal dialog + bool PressButton(int nButton); + +// Status and Settings +public: + int GetPageCount() const; + int GetActiveIndex() const; + CPropertyPageT<TBase>* GetActivePage() const; + CPropertyPageT<TBase>* GetPage(int nPage) const; + int GetPageIndex(CPropertyPageT<TBase>* pPage); + HWND GetTabControl() const; + void SetWizardMode(); + void SetHelp(bool bHelp); + void SetFinishText(LPCTSTR lpszText); + void SetWizardButtons(DWORD dwFlags); + void EnableStackedTabs(BOOL bStacked); + bool IsWizard() const; + bool SetActivePage(int nPage); + bool SetActivePage(CPropertyPageT<TBase>* pPage); + void SetTitle(LPCTSTR lpszText, UINT nStyle = 0); + +// Message Map +protected: +typedef CPropertySheetT<TBase> sheetClass; +BEGIN_MSG_MAP(sheetClass) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand) + MESSAGE_HANDLER(WM_CLOSE, OnClose) + COMMAND_HANDLER(IDCANCEL, BN_CLICKED, OnEndCode) + COMMAND_HANDLER(IDOK, BN_CLICKED, OnEndCode) + COMMAND_HANDLER(ID_WIZFINISH, BN_CLICKED, OnEndCode) +END_MSG_MAP() + +// Message Handlers + LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnEndCode(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + + +// Implementation +protected: + void BuildPropPageArray(); // Finalizes the Array of Pages + + // Used during creation to set styles + static int CALLBACK PropSheetCallback(HWND, UINT nMsg, LPARAM lParam); + + // For hooking into creation and subclassing the window + DECLARE_HOOK_AND_SUBCLASS(sheetClass); + + // Style cache (used in PropSheetCallback) + DWORD m_dwCurStyle; + DWORD m_dwCurExStyle; + +// Data +protected: + CSimpleArray< CPropertyPageT<TBase>* > m_pages; // array of CPropertyPageT pointers + LPTSTR m_szCaption; // caption of the pseudo-dialog + bool m_bStacked; // EnableStackedTabs sets this + bool m_bModeless; // TRUE when Create called instead of DoModal + int m_nDlgRet; // Result from EndDialog + +public: + PROPSHEETHEADER m_psh; +}; + +// All Initialization here +template <class TBase> +void CPropertySheetT<TBase>::CommonConstruct(LPCTSTR szCaption, + HWND hwndParent /*= NULL*/, + UINT iSelectPage /*= 0*/) +{ + // Clear + memset(&m_psh, 0, sizeof(m_psh)); + + m_psh.dwSize = sizeof(m_psh); + m_psh.dwFlags = PSH_PROPSHEETPAGE; + m_psh.nStartPage = iSelectPage; + + // Allocate String + if(m_szCaption && _tcslen(m_szCaption) < _tcslen(szCaption)) + { + delete[] m_szCaption; + m_szCaption = NULL; + } + + if(!m_szCaption) + m_szCaption = new TCHAR[_tcslen(szCaption) + 1]; + + _tcscpy(m_szCaption, szCaption); + m_psh.pszCaption = m_szCaption; + + m_bStacked = true; // Tab Control + m_bModeless = false; + m_dwCurStyle = 0; + m_dwCurExStyle = 0; + m_nDlgRet = 0; + + // m_psh.hwndParent set in DoModal/create +} + +// Callback used to set styles of Property Sheet +template <class TBase> +int CALLBACK CPropertySheetT<TBase>::PropSheetCallback(HWND hwnd, UINT nMsg, + LPARAM lParam) +{ + switch (nMsg) + { + case PSCB_PRECREATE: + { + // Extract Thunk Create (whatever) data + CPropertySheetT<TBase>* pThis = (CPropertySheetT<TBase>*)_Module.ExtractCreateWndData(); + // We need it later in the proces so add it back again + _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis); + + LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lParam; + if (lpTemplate->style != pThis->m_dwCurStyle || + lpTemplate->dwExtendedStyle != pThis->m_dwCurExStyle) + { + + // Mark the dialog template as read-write. + DWORD dwOldProtect; + VirtualProtect(lpTemplate, sizeof(DLGTEMPLATE), PAGE_READWRITE, + &dwOldProtect); + + // Ensure DS_SETFONT is set correctly. + lpTemplate->style = lpTemplate->style & DS_SETFONT ? + pThis->m_dwCurStyle | DS_SETFONT : + pThis->m_dwCurStyle & ~DS_SETFONT; + + lpTemplate->dwExtendedStyle = pThis->m_dwCurExStyle; + } + return TRUE; + } + case PSCB_INITIALIZED: + return TRUE; + + } + + return 0; +} + +// Creates a Modeless Property Sheet +template <class TBase> +bool CPropertySheetT<TBase>::Create(HWND hwndParent /*= NULL*/, DWORD dwStyle /*= (DWORD)-1*/, + DWORD dwExStyle /*= 0*/) +{ + // Calculate the default window style. + if (dwStyle == (DWORD)-1) + { + dwStyle = DS_MODALFRAME | DS_3DLOOK | DS_SETFONT | WS_POPUP | + WS_VISIBLE | WS_CAPTION; + + // Wizards don't have WS_SYSMENU by default + if (!IsWizard()) + dwStyle |= WS_SYSMENU; + } + + // Cache the styles (for use in PropSheetCallback) + m_dwCurStyle = dwStyle; + m_dwCurExStyle = dwExStyle; + + ATLASSERT(m_hWnd == NULL); + + // finish building PROPSHEETHEADER structure + BuildPropPageArray(); + + // Some more settings + m_bModeless = true; + m_psh.dwFlags |= (PSH_MODELESS | PSH_USECALLBACK); + m_psh.pfnCallback = PropSheetCallback; + m_psh.hwndParent = hwndParent; + + // Add Create Thunk whatever Data + _Module.AddCreateWndData(&m_thunk.cd, this); + // Hook into creation so we can subclass before any messages come in + HOOK_AND_SUBCLASS_NEXT(); + + // Do it! + HWND hWnd = (HWND)::PropertySheet((PROPSHEETHEADER*)&m_psh); + + // Modeless so we return right away +#ifdef _DEBUG + DWORD dwError = ::GetLastError(); +#endif + + if (hWnd == NULL || hWnd == (HWND)-1) + { +#ifdef _DEBUG + ATLTRACE("PropertySheet() failed: GetLastError returned %d\n", dwError); +#endif + return false; + } + + m_hWnd = hWnd; + + return true; +} + +// Create a Modal Dialog +template <class TBase> +int CPropertySheetT<TBase>::DoModal(HWND hwndParent /*= NULL*/, DWORD dwStyle /*= (DWORD)-1*/, + DWORD dwExStyle /*= 0*/) +{ + ATLASSERT(m_hWnd == NULL); + + // Calculate the default window style. + if (dwStyle == (DWORD)-1) + { + dwStyle = DS_MODALFRAME | DS_3DLOOK | DS_SETFONT | WS_POPUP | + WS_VISIBLE | WS_CAPTION; + + // Wizards don't have WS_SYSMENU by default + if (!IsWizard()) + dwStyle |= WS_SYSMENU; + } + + // Cache the styles (for use in PropSheetCallback) + m_dwCurStyle = dwStyle; + m_dwCurExStyle = dwExStyle; + + // finish building PROPSHEETHEADER structure + BuildPropPageArray(); + + // Set options + m_bModeless = false; + m_nDlgRet = -1; + m_psh.dwFlags |= (PSH_USECALLBACK); + m_psh.pfnCallback = PropSheetCallback; + m_psh.hwndParent = hwndParent; + + // Add Create Thunk whatever Data + _Module.AddCreateWndData(&m_thunk.cd, this); + // Hook into creation so we can subclass before any messages come in + HOOK_AND_SUBCLASS_NEXT(); + + // Do it. Doesn't come back until after the fact + int nRet = ::PropertySheet((PROPSHEETHEADER*)&m_psh); + + if(nRet == -1) + return nRet; + + return m_nDlgRet; +} + +// Finalize the Array +template <class TBase> +void CPropertySheetT<TBase>::BuildPropPageArray() +{ + // delete existing prop page array + delete[] (PROPSHEETPAGE*)m_psh.ppsp; + m_psh.ppsp = NULL; + + // build new prop page array + PROPSHEETPAGE* ppsp = new PROPSHEETPAGE[m_pages.GetSize()]; + m_psh.ppsp = (PROPSHEETPAGE*)ppsp; + BOOL bWizard = (m_psh.dwFlags & (PSH_WIZARD)); + for (int i = 0; i < m_pages.GetSize(); i++) + { + CPropertyPageT<TBase>* pPage = GetPage(i); + memcpy(&ppsp[i], &pPage->m_psp, sizeof(pPage->m_psp)); +// pPage->PreProcessPageTemplate((PROPSHEETPAGE&)ppsp[i], bWizard); + } + m_psh.nPages = m_pages.GetSize(); +} + +// Adds a Page (either before or after we're on the screen) +template <class TBase> +void CPropertySheetT<TBase>::AddPage(CPropertyPageT<TBase>* pPage) +{ + ATLASSERT(pPage != NULL); + + // Add page to internal list + m_pages.Add(pPage); + pPage->m_pSheet = this; + + // Add page externally + if (m_hWnd != NULL) + { + // build new prop page array + PROPSHEETPAGE* ppsp = new PROPSHEETPAGE[m_pages.GetSize()]; + memcpy(ppsp, m_psh.ppsp, sizeof(PROPSHEETPAGE) * (m_pages.GetSize() - 1)); + delete[] (PROPSHEETPAGE*)m_psh.ppsp; + m_psh.ppsp = ppsp; + ppsp += m_pages.GetSize() - 1; + + // copy processed PROPSHEETPAGE struct to end + memcpy(ppsp, &(pPage->m_psp), sizeof(pPage->m_psp)); +// pPage->PreProcessPageTemplate((PROPSHEETPAGE&)*ppsp, IsWizard()); + HPROPSHEETPAGE hPSP = CreatePropertySheetPage((PROPSHEETPAGE*)ppsp); + ATLASSERT(hPSP != NULL); + + // Tray and add it + if (!SendMessage(PSM_ADDPAGE, 0, (LPARAM)hPSP)) + { + DestroyPropertySheetPage(hPSP); + ATLASSERT(false); + } + } +} + +// Removes a Page (either before or after we're on the screen) +template <class TBase> +void CPropertySheetT<TBase>::RemovePage(CPropertyPageT<TBase>* pPage) +{ + ATLASSERT(pPage != NULL); + + // Get Index + int nPage = GetPageIndex(pPage); + pPage->m_pSheet = NULL; + ATLASSERT(nPage >= 0); + + RemovePage(nPage); +} + +// Removes a Page (either before or after we're on the screen) +template <class TBase> +void CPropertySheetT<TBase>::RemovePage(int nPage) +{ + // remove the page externally + if (m_hWnd != NULL) + SendMessage(PSM_REMOVEPAGE, nPage); + + // remove the page from internal list + m_pages.RemoveAt(nPage); +} + +// Closes the Property Sheet +template <class TBase> +void CPropertySheetT<TBase>::EndDialog(int nEndID) +{ + m_nDlgRet = nEndID; + + if (m_bModeless) + DestroyWindow(); + else + PostMessage(PSM_PRESSBUTTON, PSBTN_CANCEL); +} + +// Need to handle WM_CLOSE for Modeless Property Sheets +template <class TBase> +LRESULT CPropertySheetT<TBase>::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + if (m_bModeless) + DestroyWindow(); + else + bHandled = false; + + return 0; +} + +// Need to handle SC_CLOSE for Modeless Property Sheets +template <class TBase> +LRESULT CPropertySheetT<TBase>::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + switch (wParam & 0xFFF0) + { + case SC_CLOSE: + if (m_bModeless) + { + SendMessage(WM_CLOSE); + return 0; + } + } + bHandled = false; + return 0; +} + +// Returns number of Pages +template <class TBase> +int CPropertySheetT<TBase>::GetPageCount() const +{ + if (m_hWnd == NULL) + return m_pages.GetSize(); + + return TabCtrl_GetItemCount(GetTabControl()); +} + +// Returns Current Page +template <class TBase> +int CPropertySheetT<TBase>::GetActiveIndex() const +{ + if (m_hWnd == NULL) + return m_psh.nStartPage; + + return TabCtrl_GetCurSel(GetTabControl()); +} + +// Moves to Page +template <class TBase> +bool CPropertySheetT<TBase>::SetActivePage(int nPage) +{ + if (m_hWnd == NULL) + { + m_psh.nStartPage = nPage; + return true; + } + return (bool)SendMessage(PSM_SETCURSEL, nPage); +} + +// Moves to Page +template <class TBase> +bool CPropertySheetT<TBase>::SetActivePage(CPropertyPageT<TBase>* pPage) +{ + ATLASSERT(pPage != NULL); + + int nPage = GetPageIndex(pPage); + ATLASSERT(pPage >= 0); + + return SetActivePage(nPage); +} + +// Gets number of Page +template <class TBase> +int CPropertySheetT<TBase>::GetPageIndex(CPropertyPageT<TBase>* pPage) +{ + ATLASSERT(pPage != NULL); + for (int i = 0; i < GetPageCount(); i++) + { + if (GetPage(i) == pPage) + return i; + } + return -1; // pPage not found +} + +// Get a Page from Array +template <class TBase> +CPropertyPageT<TBase>* CPropertySheetT<TBase>::GetPage(int nPage) const + { return m_pages[nPage]; } + +// Initdialog: Complete creation and setup for modeless etc... +template <class TBase> +LRESULT CPropertySheetT<TBase>::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + // Change tab style if scrolling tabs desired (stacked tabs are default) + if (!m_bStacked) + ((CWindow)GetTabControl()).ModifyStyle(TCS_MULTILINE, TCS_SINGLELINE, 0); + + // For Property Sheets + if (!IsWizard()) + { + // Resize the tab control so the layout is less restrictive + HWND hWndTab = ::GetDlgItem(m_hWnd, AFX_IDC_TAB_CONTROL); + ATLASSERT(hWndTab != NULL); + RECT rcOld; + ::GetWindowRect(hWndTab, &rcOld); + ScreenToClient(&rcOld); + RECT rcNew = {0, 0, 0, 32}; + ::MapDialogRect(m_hWnd, &rcNew); + if (rcNew.bottom < rcNew.bottom) + { + // Move tab control + int cyDiff = (rcOld.bottom - rcOld.top) - rcNew.bottom; + ::SetWindowPos(hWndTab, NULL, 0, 0, rcOld.right - rcOld.left, rcNew.bottom, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + + // Move buttons by similar amount + for (int i = 0; i < _countof(_PropSheetButtons); i++) + { + HWND hWndBtn = ::GetDlgItem(m_hWnd, _PropSheetButtons[i]); + if (hWndBtn != NULL) + { + ::GetWindowRect(hWndBtn, &rcOld); + ScreenToClient(&rcOld); + ::SetWindowPos(hWndBtn, NULL, + rcOld.left, rcOld.top - cyDiff, + 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + } + } + + // Resize property sheet itself similarly + GetWindowRect(&rcOld); + SetWindowPos(NULL, 0, 0, rcOld.right - rcOld.left, (rcOld.bottom - rcOld.top) - cyDiff, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + } + } + + // For Modeless Sheets + if (m_bModeless && !IsWizard()) + { + // Layout property sheet so button area is not accounted for + RECT rcWnd; + GetWindowRect(&rcWnd); + RECT rcBtn; + HWND hWndBtn = ::GetDlgItem(m_hWnd, IDOK); + ATLASSERT(hWndBtn != NULL); + ::GetWindowRect(hWndBtn, &rcBtn); + SetWindowPos(NULL, 0, 0, + rcWnd.right - rcWnd.left, + (rcBtn.top - rcWnd.top) + ::GetSystemMetrics(SM_CYBORDER), + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + + // Remove standard buttons for modeless dialogs + for (int i = 0; i < _countof(_PropSheetButtons); i++) + { + hWndBtn = ::GetDlgItem(m_hWnd, _PropSheetButtons[i]); + if (hWndBtn != NULL) + { + ::ShowWindow(hWndBtn, SW_HIDE); + ::EnableWindow(hWndBtn, FALSE); + } + } + } + + // Center the property sheet relative to the parent window + if (!(GetStyle() & WS_CHILD)) + CenterWindow(); + + // API implementation probably needs this message + bHandled = FALSE; + return 1; +} + +// Gets the return code for DoModal +template <class TBase> +LRESULT CPropertySheetT<TBase>::OnEndCode(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) +{ + // API implementation probably needs this message + bHandled = FALSE; + m_nDlgRet = wID; + return 0; +} + + +// Are we a wizard? +template <class TBase> +bool CPropertySheetT<TBase>::IsWizard() const + { return ((m_psh.dwFlags & PSH_WIZARD) != 0); } + +// Return HWND of Tab Control +template <class TBase> +HWND CPropertySheetT<TBase>::GetTabControl() const + { ATLASSERT(::IsWindow(m_hWnd)); return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0); } + +// Press Button on Property Sheet +template <class TBase> +bool CPropertySheetT<TBase>::PressButton(int nButton) + { ATLASSERT(::IsWindow(m_hWnd)); return ::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0) ? true : false; } + +// Get the Active Page +template <class TBase> +CPropertyPageT<TBase>* CPropertySheetT<TBase>::GetActivePage() const + { return GetPage(GetActiveIndex()); } + +// Change the Title +template <class TBase> +void CPropertySheetT<TBase>::SetTitle(LPCTSTR lpszText, UINT nStyle) +{ + ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid + + // Set Internal State + if(m_szCaption && _tcslen(m_szCaption) < _tcslen(lpszText)) + { + delete[] m_szCaption; + m_szCaption = NULL; + } + + if(!m_szCaption) + m_szCaption = new TCHAR[_tcslen(lpszText) + 1]; + + _tcscpy(m_szCaption, lpszText); + m_psh.pszCaption = m_szCaption; + + // Set the options + m_psh.dwFlags &= ~PSH_PROPTITLE; + m_psh.dwFlags |= nStyle; + + if (m_hWnd != NULL) + { + // set external state + SendMessage(PSM_SETTITLE, nStyle, (LPARAM)lpszText); + } +} + +// Make us a Wizard +template <class TBase> +void CPropertySheetT<TBase>::SetWizardMode() + { m_psh.dwFlags |= PSH_WIZARD; } + +template <class TBase> +void CPropertySheetT<TBase>::SetHelp(bool bHelp) +{ + if(bHelp) + m_psh.dwFlags |= PSH_HASHELP; + else + m_psh.dwFlags &= ~(PSH_HASHELP); +} + +// Set Text of Finish Button +template <class TBase> +void CPropertySheetT<TBase>::SetFinishText(LPCTSTR lpszText) + { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText); } + +// Choose which buttons to have in Wizard +template <class TBase> +void CPropertySheetT<TBase>::SetWizardButtons(DWORD dwFlags) + { ATLASSERT(::IsWindow(m_hWnd)); ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags); } + +// Stacked Tabs +template <class TBase> +void CPropertySheetT<TBase>::EnableStackedTabs(BOOL bStacked) + { m_bStacked = bStacked; } + +typedef CPropertySheetT<CWindow> CPropertySheet; +typedef CPropertyPageT<CWindow> CPropertyPage; + +#endif // !defined(AFX_PROPERTYPAGE_H__1508DAF4_7AD1_11D3_BF96_0020182B97FC__INCLUDED_) diff --git a/win32/common/atlwinhk.h b/win32/common/atlwinhk.h new file mode 100644 index 0000000..4dddf82 --- /dev/null +++ b/win32/common/atlwinhk.h @@ -0,0 +1,151 @@ +/* + * AUTHOR + * N. Nielsen + * + * VERSION + * 2.2.0b + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + +#ifndef __ATLWINHK_H__ +#define __ATLWINHK_H__ + +///////////////////////////////////////////////////////////////////////// +// Hooks an CWindowImpl to windows that the API or other code creates +// By Stef: 06/10/99 + + +// Use this macro in the class definition and pass class name +// as first param +#define DECLARE_HOOK_AND_SUBCLASS(Class) \ + HHOOK m_hHookCur; \ + static LRESULT CALLBACK HookCreateProc(int nCode, \ + WPARAM wParam, \ + LPARAM lParam) \ + { \ + Class* pThis = (Class*) _Module.ExtractCreateWndData(); \ + \ + if (nCode != HCBT_CREATEWND) \ + { \ + /*Add it back again*/ \ + _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis); \ + /*wait for HCBT_CREATEWND just pass others on...*/ \ + return CallNextHookEx(pThis->m_hHookCur, nCode, wParam, lParam); \ + } \ + \ + pThis->SubclassWindow((HWND)wParam); \ + \ + UnhookWindowsHookEx(pThis->m_hHookCur); \ + HHOOK hHookCur = pThis->m_hHookCur; \ + pThis->m_hHookCur = NULL; \ + \ + return CallNextHookEx(hHookCur, nCode, wParam, lParam); \ + } + +// Use this *immediately* before the code that creates the window +// It will subclass the first window that's created by that thread +// so add immediately before. +#define HOOK_AND_SUBCLASS_NEXT() \ + ((m_hHookCur = SetWindowsHookEx(WH_CBT, HookCreateProc, NULL, ::GetCurrentThreadId())) == NULL) + +const LPCTSTR kDialogClass = (LPCTSTR)0x00008002; + +template<class _Class> +class CHookWindow +{ +public: + CHookWindow() + { + m_hHookCur = NULL; + m_szHookClass = NULL; + m_szHookName = NULL; + } + + bool SubclassNext(LPCTSTR szClass = NULL, LPCTSTR szName = NULL) + { + _Class* pThis = (_Class*)this; + _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis); + + m_hHookCur = SetWindowsHookEx(WH_CBT, HookCreateProc, NULL, ::GetCurrentThreadId()); + + if(m_hHookCur) + { + m_szHookClass = szClass; + m_szHookName = szName; + } + + return m_hHookCur == NULL; + } + + static LRESULT CALLBACK HookCreateProc(int nCode, WPARAM wParam, LPARAM lParam) + { + _Class* pThis = (_Class*) _Module.ExtractCreateWndData(); + HHOOK hHookCur = pThis->m_hHookCur; + + bool bSkip = false; + + if(nCode != HCBT_CREATEWND) + { + bSkip = true; + } + else + { + CBT_CREATEWND* pCreate = (CBT_CREATEWND*)lParam; + + if(pThis->m_szHookClass) + { + // If it's not a pointer (for at least two bytes) + if(IsBadReadPtr(pCreate->lpcs->lpszClass, 2) || IsBadReadPtr(pThis->m_szHookClass, 2)) + // Then just compare values + bSkip = pCreate->lpcs->lpszClass != pThis->m_szHookClass; + + else + // Otherwise compare strings + bSkip = _tcsicmp(pCreate->lpcs->lpszClass, pThis->m_szHookClass) != 0; + } + + if(pThis->m_szHookName) + { + if(IsBadReadPtr(pCreate->lpcs->lpszName, _tcslen(pThis->m_szHookName)) || + _tcsicmp(pCreate->lpcs->lpszName, pThis->m_szHookName)) + bSkip = true; + } + } + + if(bSkip) + { + /*Add it back again*/ + _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis); + } + else + { + pThis->SubclassWindow((HWND)wParam); + + UnhookWindowsHookEx(pThis->m_hHookCur); + pThis->m_hHookCur = NULL; + } + + return CallNextHookEx(hHookCur, nCode, wParam, lParam); + } + +protected: + HHOOK m_hHookCur; + LPCTSTR m_szHookName; + LPCTSTR m_szHookClass; +}; + + +#endif //__ATLWINHK_H__ diff --git a/win32/common/droplet.cpp b/win32/common/droplet.cpp new file mode 100644 index 0000000..e796f49 --- /dev/null +++ b/win32/common/droplet.cpp @@ -0,0 +1,226 @@ +/* + * AUTHOR + * N. Nielsen + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + +#include <stdafx.h> +#include "lib/rep.h" +#include "common/binfile.h" +#include "common/repfile.h" +#include "Droplet.h" + +// (Con|De)struction: -------------------------------------------- + +Droplet::Droplet() +{ + m_keepBackups = false; + memset(&m_ctx, 0, sizeof(m_ctx)); +} + +Droplet::~Droplet() +{ + repFree(&m_ctx); +} + + +// All error handling jumps to 'cleanup' where wrapping up loose +// ends is done +#define RETURN(v) { ret = v; goto cleanup; } + + +// save: --------------------------------------------------- +// Saves a droplet to a file. The file must already exist +// and must be an executable + +bool Droplet::save(LPCTSTR fileName) +{ + HANDLE update = NULL; + void* data = NULL; + BFILE h = NULL; + bool ret = true; + + { + if(!m_ctx.script.ops) + RETURN(false); + + // Make the rep binfile + bfval val; + BFILE h = bfStartMem(NULL, 0, BF_REALLOC); + if(!h) RETURN(false); + + // Write out the headers + repfWriteHeader(h); + + // Write to it now + if(m_ctx.block != 0) + bfWriteInt(h, REPVAL_BUFSIZE, m_ctx.block); + + bfWriteInt(h, DROPVAL_BACKUPS, m_keepBackups ? 1 : 0); + + // Write the script out + val.id = REPVAL_SCRIPT; + val.len = m_ctx.script.len; + val.type = BINTYPE_DATA; + bfWriteValue(h, &val, m_ctx.script.ops); + + if(!m_title.empty()) + bfWriteString(h, DROPVAL_TITLE, m_title.c_str()); + + // Done + bfWriteEnd(h); + if(bfError(h)) RETURN(false); + + size_t len = bfCount(h); + data = bfInternal(h); + bfClose(h); + h = NULL; + + // Now actually modify the EXE + update = BeginUpdateResource(fileName, FALSE); + if(!update) RETURN(false); + + if(!UpdateResource(update, DROP_RESOURCE_TYPE, DROP_RESOURCE_ID, + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), data, len) + || !EndUpdateResource(update, FALSE)) + RETURN(false); + + update = NULL; + } + +cleanup: + while(data) + { + free(data); + + if(h == NULL) + break; + + data = bfInternal(h); + bfClose(h); + h = NULL; + } + + if(update) + EndUpdateResource(update, TRUE); + + return true; +} + + +// load: --------------------------------------------------------------- +// Load a droplet from a file + +bool Droplet::load(LPCTSTR fileName) +{ + HMODULE module = LoadLibrary(fileName); + if(!module) + return false; + + bool ret = load(GetModuleHandle(fileName)); + + FreeLibrary(module); + + return ret; +} + + +// load: --------------------------------------------------------------- +// Load a droplet from a loaded module + +bool Droplet::load(HMODULE module) +{ + bool ret = true; + BFILE h = NULL; + + { + // In case we're called twice + repFree(&m_ctx); + + // Load the resource + HRSRC hRsrc = FindResourceEx(module, DROP_RESOURCE_TYPE, DROP_RESOURCE_ID, + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)); + if(!hRsrc) RETURN(false); + + HGLOBAL hGlobal = LoadResource(module, hRsrc); + if(!hGlobal) RETURN(false); + + void* data = LockResource(hGlobal); + if(!data) RETURN(false); + + ::SetLastError(0); + + // And now read it + h = bfStartMem(data, SizeofResource(module, hRsrc), 0); + if(!h) RETURN(false); + + // Check the format + if(!repfReadHeader(h)) + RETURN(false); + + bfval val; + + while(bfReadValueInfo(h, &val)) + { + switch(val.id) + { + case REPVAL_BUFSIZE: + bfReadValueData(h, &val, &(m_ctx.block)); + continue; + + case DROPVAL_BACKUPS: + { + long value; + bfReadValueData(h, &val, &value); + m_keepBackups = value == 0 ? false : true; + } + continue; + + case REPVAL_SCRIPT: + { + // Script must have some length + if(val.len == 0) + RETURN(false); + + m_ctx.script.ops = (byte*)malloc(val.len); + if(!m_ctx.script.ops) + RETURN(false); + + bfReadValueData(h, &val, m_ctx.script.ops); + m_ctx.script.len = val.len; + } + continue; + + case DROPVAL_TITLE: + { + bfReadValueData(h, &val, m_title.get_buffer(val.len)); + m_title.release_buffer(); + } + continue; + + } + + bfSkipValueData(h, &val); + } + } + +cleanup: + if(h) + bfClose(h); + + return ret; +} + diff --git a/win32/common/droplet.h b/win32/common/droplet.h new file mode 100644 index 0000000..e98725e --- /dev/null +++ b/win32/common/droplet.h @@ -0,0 +1,98 @@ +/* + * AUTHOR + * N. Nielsen + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + + +#ifndef __DROPLET_H__ +#define __DROPLET_H__ + + +// The resources in the droplet +#define DROP_RESOURCE_TYPE _T("REP") +#define DROP_RESOURCE_ID _T("SCRIPT") +#define DROP_RESOURCE_FILE _T("DROPLET") + +// Some extra binfile tags +#define DROPVAL_TITLE 0x0101 +#define DROPVAL_BACKUPS 0x0102 + +#include "lib/rlib.h" +#include "lib/rep.h" + + +// Droplet: --------------------------------------------------------------- +// A droplet provides the saving/loading/loaded functionality of the +// droplet. Replaces are not done here + +class Droplet +{ +public: + Droplet(); + ~Droplet(); + + // Load a droplet from a file + bool load(LPCTSTR fileName); + + // Load a droplet from a loaded executable + bool load(HMODULE module); + + // Save a droplet out to an existing executable + bool save(LPCTSTR fileName); + + + // Get the internal rlib stream + r_context& getContext() + { return m_ctx; } + + // Is there a valid script loaded + bool hasScript() + { return m_ctx.script.ops != NULL; } + + // Get dialog title stored in droplet + string getTitle() + { return m_title; } + + // Set dialog title stored in droplet + void setTitle(astring& title) + { m_title = title; } + + // Get the buffer size stored in droplet + // 0 = process entire file + size_t getBuffSize() + { return m_ctx.block; } + + // Set the buffer size to be stored in droplet + void setBuffSize(size_t buffSize) + { m_ctx.block = buffSize; } + + // Should backups be kept? + bool keepBackups() + { return m_keepBackups; } + + // Set backup options for droplet + void setBackups(bool backups) + { m_keepBackups = backups; } + +protected: + r_context m_ctx; + + astring m_title; // The dialog title + bool m_keepBackups; // Should backups be kept? +}; + +#endif //__DROPLET_H__
\ No newline at end of file diff --git a/win32/common/errutil.cpp b/win32/common/errutil.cpp new file mode 100644 index 0000000..302b4fa --- /dev/null +++ b/win32/common/errutil.cpp @@ -0,0 +1,106 @@ +/* + * AUTHOR + * N. Nielsen + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + +#include "stdafx.h" +#include "rliberr.h" +#include "errutil.h" + +// rlibError: ------------------------------------------------------------- +// Displays errors from rlib. Assumes we have the appropriate +// error codes compiled in as resources + +HRESULT rlibError(HWND parent, int code, r_script* script) +{ + ASSERT(code < 0); + USES_CONVERSION; + + LPVOID lpMsgBuf; + HRESULT hr = HRESULT_FROM_RLIB(code); + string message; + + DWORD dwRet = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_MAX_WIDTH_MASK, GetModuleHandle(NULL), hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf, 0, NULL); + if(dwRet && lpMsgBuf) + { + message.append((LPTSTR)lpMsgBuf); + + // Free the buffer. + ::LocalFree(lpMsgBuf); + + // If there was a specific error message then tack that on + if(script->error) + { + message.append(_T("\n\n")); + message.append(A2T(script->error)); + } + + // If there's an error line then tack that on + if(script->errline != 0) + { + string line; + line.format(_T(" (near line %d)"), script->errline); + message.append(line); + } + + MessageBox(parent, message.c_str(), _T("Rep Droplet"), MB_OK | MB_ICONSTOP); + } + + return hr; +} + + +// errorMessage: ----------------------------------------------------------- +// Displays standard windows errors. + +HRESULT errorMessage(HWND parent, HRESULT hr, LPCTSTR format, ...) +{ + string message; + + va_list ap; + va_start(ap, format); + + message.format_v(format, ap); + + va_end(ap); + + if(FAILED(hr)) + { + LPVOID lpMsgBuf; + + DWORD dwRet = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, 0, NULL); + if(dwRet && lpMsgBuf) + { + message.append(_T("\n\n")); + message.append((LPTSTR)lpMsgBuf); + message.resize(message.size() - 2); // Take off new line + + // Free the buffer. + ::LocalFree(lpMsgBuf); + } + } + + MessageBox(parent, message.c_str(), _T("Rep Droplet"), MB_OK | MB_ICONSTOP); + + return hr == S_OK ? E_FAIL : hr; +} diff --git a/win32/common/errutil.h b/win32/common/errutil.h new file mode 100644 index 0000000..0804149 --- /dev/null +++ b/win32/common/errutil.h @@ -0,0 +1,32 @@ +/* + * AUTHOR + * N. Nielsen + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + +#ifndef __ERRUTIL_H__ +#define __ERRUTIL_H__ + +#include "lib/rlib.h" + +// Display a standard windows error message +HRESULT errorMessage(HWND parent, HRESULT hr, LPCTSTR format, ...); + +// Display an rlib error message +HRESULT rlibError(HWND parent, int code, r_script* script); + + +#endif //__ERRUTIL_H__
\ No newline at end of file diff --git a/win32/common/mystring.h b/win32/common/mystring.h new file mode 100644 index 0000000..470ac3c --- /dev/null +++ b/win32/common/mystring.h @@ -0,0 +1,536 @@ +/* + * AUTHOR + * N. Nielsen + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + +#if !defined(_MYSTRING_H_) +#define _MYSTRING_H_ + +////////////////////////////////////////////////////////////////////////////// + +#include <tchar.h> + +#include <stdarg.h> + +#include <string> +#include <locale> + +#pragma warning(push) +#pragma warning(disable:4786) // Disable warning for names > 256 + +////////////////////////////////////////////////////////////////////////////// + +template<typename T> +class stringT : public std::basic_string<T> // T should be either char or wchar_t +{ +public: + // Constructors + stringT() + : std::basic_string<T>() + { } + + stringT(const stringT<T>& strInput) + : std::basic_string<T>(strInput) + { } + + + stringT(const std::basic_string<T>& strInput) + : std::basic_string<T>(strInput) + { } + + stringT(const std::basic_string<T>& strInput, size_type pos, size_type n) + : std::basic_string<T>(strInput, pos, n) + { } + + stringT(const std::basic_string<T>::const_iterator first, + const std::basic_string<T>::const_iterator last) + : std::basic_string<T>(first, last) + { } + + + stringT(const T* strInput) + : std::basic_string<T>(strInput) + { } + + + stringT(const T* strInput, size_type n) + : std::basic_string<T>(strInput, n) + { } + + +#ifdef _INC_COMDEF + stringT(_bstr_t bstr) + { + (*this) = (const T*)bstr; + } +#endif + + stringT(T ch, int nRepeat = 1) + : std::basic_string<T>(nRepeat, ch) + { } + + + // Other Conversions + stringT<T>& make_upper() + { + std::ctype<T> c; + T* p = get_buffer(); + c.toupper(p, p + size()); + release_buffer(); + return *this; + } + + stringT<T> upper() const + { + stringT<T> sTmp(*this); + sTmp.make_upper(); + return sTmp; + } + + stringT<T>& make_lower() + { + std::ctype<T> c; + T* p = get_buffer(); + c.tolower(p, p + size()); + release_buffer(); + return *this; + } + + stringT<T> lower() const + { + stringT<T> sTmp(*this); + sTmp.make_lower(); + return sTmp; + } + + void trim_left() + { + // TODO: Optimize + while(!empty() && _istspace(at(0))) + erase(0, 1); + } + + void trim_right() + { + // TODO: Optimize + while(!empty() && _istspace(at(length()-1))) + erase(length() - 1, 1); + } + + void trim() + { + trim_left(); + trim_right(); + } + + const stringT<T>& format(const T* pszFormat, ...) + { + va_list vl; + va_start(vl, pszFormat); + format_v(pszFormat, vl); + va_end(vl); + + return *this; + } + +#ifdef _WINDOWS_ + + const stringT<T>& format(HINSTANCE hInst, UINT nID, ... ) + { + stringT<T> sTemp; + sTemp.load_string(hInst, nID); + + va_list vl; + va_start(vl, nID); + format_v(sTemp, vl); + va_end(vl); + + return *this; + } + +#ifdef __ATLBASE_H__ + const stringT<T>& format(UINT nID, ... ) + { + stringT<T> sTemp; + sTemp.load_string(nID); + + va_list vl; + va_start(vl, nID); + format_v(sTemp, vl); + va_end(vl); + + return *this; + } +#endif // __ATLBASE_H__ + +#endif + + void format_v(const char* pszFormat, va_list vl) + { + // Copied Code.... + + // Doesn't have all the features of CString::Format() + T* pszTemp = NULL; + size_t nBufferSize = 32; + int nRetVal = -1; + + do + { + // Double the buffer size for next time around + nBufferSize += nBufferSize; + delete [] pszTemp; + pszTemp = new T [nBufferSize]; + nRetVal = _vsnprintf(pszTemp, nBufferSize, pszFormat, vl); + } while (nRetVal < 0); + + *this = pszTemp; + delete [] pszTemp; + + return; + } + + void format_v(const wchar_t* pszFormat, va_list vl) + { + // Copied Code.... + + // Doesn't have all the features of CString::Format() + T* pszTemp = NULL; + size_t nBufferSize = 32; + int nRetVal = -1; + + do + { + // Double the buffer size for next time around + nBufferSize += nBufferSize; + delete [] pszTemp; + pszTemp = new T [nBufferSize]; + nRetVal = _vsnwprintf(pszTemp, nBufferSize, pszFormat, vl); + } while (nRetVal < 0); + + *this = pszTemp; + delete [] pszTemp; + + return; + } + + int replace(const std::basic_string<T>& sFind, const std::basic_string<T>& sReplace, bool bMultiple = true, size_type nStart = 0) + { + stringT<T> sTemp = *this; + int nReplaced = 0; + + if((nStart = sTemp.find(sFind, nStart)) != npos) + { + sTemp.erase(nStart, sFind.length()); + sTemp.insert(nStart, sReplace); + nReplaced++; + } + + while(bMultiple && (nStart = sTemp.find(sFind, nStart + 1)) != npos) + { + sTemp.erase(nStart, sFind.length()); + sTemp.insert(nStart, sReplace); + nReplaced++; + } + + *this = sTemp; + return nReplaced; + } + + // Operators + + T operator[](int nIndex) const + { return at(nIndex); }; + +#ifdef _INC_COMDEF + operator _bstr_t() const + { return _bstr_t(c_str()); }; +#endif + + operator const T*() const + { return c_str(); }; + + + // Buffer Operations + // Derived code from MFC CString + T* get_buffer(size_t sz = npos) + { + if(sz == npos) + sz = size(); + + resize(sz + 1); + // Make sure we generate a write command + // so we have no extra references + // TODO: Does basic_string use reference counting? + // (much later) A: Yes it does! Reference is in the bytes before data + at(sz) = 0; + return const_cast<T*>(data()); + } + + void release_buffer() + { + if(!empty()) + { + // Make sure we generate a write command + // Find the null terminated end + for(string::size_type i = 0; i < capacity() && i < size(); i++) + if(at(i) == 0) + break; + + ASSERT(i != capacity()); + resize(i); + } + } + + void clear() + { resize(0); } + +#ifdef _WINDOWS_ + bool load_string(HINSTANCE hInst, unsigned int nID) + { + string::size_type nSize = 0x80; + do + { + release_buffer(); + nSize *= 2; + } + while(load_string(hInst, nID, get_buffer(nSize), nSize) == nSize); + + release_buffer(); + return nSize > 0; + } +#endif // WIN32 + +#ifdef __ATLBASE_H__ + bool load_string(unsigned int nID) + { + string::size_type nSize = 0x80; + do + { + release_buffer(); + nSize *= 2; + } + while(load_string(_Module.m_hInstResource, nID, get_buffer(nSize), nSize) == nSize); + + release_buffer(); + return nSize > 0; + } +#endif // __ATLBASE_H__ + + +protected: + +#ifdef _WINDOWS_ + + static int load_string(HINSTANCE hInst, UINT nID, char* pBuff, size_t nSize) + { + return ::LoadStringA(hInst, nID, pBuff, nSize); + } + + static int load_string(HINSTANCE hInst, UINT nID, wchar_t* pBuff, size_t nSize) + { +#ifdef _UNICODE + return ::LoadStringW(hInst, nID, pBuff, nSize); +#else + char* pABuff = new char[nSize]; + if(!pABuff) return 0; + + int nRet = load_string(hInst, nID, pABuff, nSize); + if(nRet) + { + pBuff[0] = L'\0'; + MultiByteToWideChar(GetACP(), 0, pABuff, -1, pBuff, nSize); + } + + return nRet; +#endif + } + + + +#endif + + +}; + + #ifndef _UNICODE + typedef stringT<char> string; + #else + typedef stringT<wchar_t> string; + #endif + + typedef stringT<char> astring; + typedef stringT<wchar_t> wstring; + + +template<typename T> +class cstringT +{ +public: + cstringT() + { clear(); }; + cstringT(const T* ptr, size_t len) + { set(ptr, len); }; + + operator stringT<T>() const + { + if(_Ptr) + return stringT<T>(_Ptr, _Len); + else + return stringT<T>(); + }; + + bool is_null() const + { return _Ptr ? false : true; } + // TODO: Maybe some validity checks + void set(const T* ptr, size_t len) + { _Ptr = ptr; _Len = len; } + void clear() + { _Ptr = 0; _Len = 0; } + +protected: + const T* _Ptr; + size_t _Len; +}; + + + #ifndef _UNICODE + typedef cstringT<char> cstring; + #else + typedef cstringT<wchar_t> cstring; + #endif + + typedef cstringT<char> castring; + typedef cstringT<wchar_t> cwstring; + + + +#include <vector> +#include <algorithm> + +template<typename S> +class string_arrayT : public std::vector<S> +{ +public: + string_arrayT(const std::vector<S> & x) + : std::vector<S>(x) {}; + string_arrayT(string_arrayT & x) + : std::vector<S>(x) {}; + string_arrayT(std::vector<S>::const_iterator first, std::vector<S>::const_iterator last, const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type()) + : std::vector<S>(first, last, al) {}; + explicit string_arrayT(const const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type()) + : std::vector<S>(al) {}; + explicit string_arrayT(std::vector<S>::size_type n, const std::vector<S>::value_type& v = std::vector<S>::value_type(), const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type()) + : std::vector<S>(n, v, al) {}; + + std::vector<S>::size_type split(S sIn, S sDelim, bool bTrim = false) + { + S::size_type start = 0; + S::size_type ed = 0; + std::vector<S>::size_type cnt = 0; + S::size_type lenDelim = sDelim.size(); + S sTemp; + + if(lenDelim == 0) + { + if(bTrim) + sIn.trim(); + push_back(sIn); + return 1; + } + + while(ed != string::npos) + { + ed = sIn.find(sDelim, start); + if(ed == string::npos) + sTemp = sIn.substr(start); + else + sTemp = sIn.substr(start, ed - start); + + if(bTrim) + sTemp.trim(); + + push_back(sTemp); + + cnt++; + + start = ed + lenDelim; + } + + return cnt; + } + + S join(S sDelim) const + { + S sTemp; + const_iterator it = begin(); + const_iterator ed = end(); + + while(it != ed) + { + sTemp += *it; + it++; + } + + return sTemp; + } + + class no_case + { + public: + no_case(const S& s) : _str(s) + { _str.make_lower(); } + + bool operator()(const S& s) + { return s.lower() == _str; } + protected: + S _str; + }; + + bool has(S sVal, bool bCase = true) const + { return find(sVal, bCase) != end(); } + + const_iterator find(S sVal, bool bCase = true) const + { + if(bCase) + return std::find(begin(), end(), sVal); + else + { + no_case fndr(sVal); + return std::find_if(begin(), end(), fndr); + } + } + + iterator find(S sVal, bool bCase = true) + { + if(bCase) + return std::find(begin(), end(), sVal); + else + { + no_case fndr(sVal); + return std::find_if(begin(), end(), fndr); + } + } +}; + +typedef string_arrayT< string > string_array; +typedef string_arrayT< wstring > wstring_array; + +////////////////////////////////////////////////////////////////////////////// + +#pragma warning( pop ) + +#endif // !defined(_MYSTRING_H_) diff --git a/win32/common/rep.ico b/win32/common/rep.ico Binary files differnew file mode 100644 index 0000000..51cf5f8 --- /dev/null +++ b/win32/common/rep.ico diff --git a/win32/common/rliberr.h b/win32/common/rliberr.h new file mode 100644 index 0000000..8fe3a80 --- /dev/null +++ b/win32/common/rliberr.h @@ -0,0 +1,136 @@ +/* + * AUTHOR + * N. Nielsen + * + * VERSION + * 2.2.0b + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + +#ifndef _RLIBERR_H_ +#define _RLIBERR_H_ + +#ifndef _WINERROR_ + #error Include winerror.h first. +#endif + +#define HRESULT_FROM_RLIB(code) \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_RLIB, abs(code)) + +/* ------------------------------------------------------------------------ *\ + Rlib Errors +\* ------------------------------------------------------------------------ */ +// +// Values are 32 bit values layed out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// +#define FACILITY_RLIB 0x196 + + +// +// Define the severity codes +// + + +// +// MessageId: RLIB_E_NOMEM +// +// MessageText: +// +// Out of Memory. +// +#define RLIB_E_NOMEM ((HRESULT)0x81960001L) + +// +// MessageId: RLIB_E_SYNTAX +// +// MessageText: +// +// Rep script syntax error. +// +#define RLIB_E_SYNTAX ((HRESULT)0x81960002L) + +// +// MessageId: RLIB_E_REGEXP +// +// MessageText: +// +// Regular expression syntax error. +// +#define RLIB_E_REGEXP ((HRESULT)0x81960003L) + +// +// MessageId: RLIB_E_LOOP +// +// MessageText: +// +// Rep encountered an endless loop. +// +#define RLIB_E_LOOP ((HRESULT)0x81960004L) + +// +// MessageId: RLIB_E_USER +// +// MessageText: +// +// User defined error. +// +#define RLIB_E_USER ((HRESULT)0x81960005L) + +// +// MessageId: RLIB_E_IOERR +// +// MessageText: +// +// There was an error reading or writing the data. +// +#define RLIB_E_IOERR ((HRESULT)0x81960006L) + +// +// MessageId: RLIB_E_INVARG +// +// MessageText: +// +// Programmer Error: Invalid argument. +// +#define RLIB_E_INVARG ((HRESULT)0x8196000AL) + +#endif // _RLIBERR_H_
\ No newline at end of file diff --git a/win32/common/rliberr.mc b/win32/common/rliberr.mc new file mode 100644 index 0000000..50ac61f --- /dev/null +++ b/win32/common/rliberr.mc @@ -0,0 +1,106 @@ +;/* +; * AUTHOR +; * N. Nielsen +; * +; * VERSION +; * 2.2.0b +; * +; * LICENSE +; * This software is in the public domain. +; * +; * The software is provided "as is", without warranty of any kind, +; * express or implied, including but not limited to the warranties +; * of merchantability, fitness for a particular purpose, and +; * noninfringement. In no event shall the author(s) be liable for any +; * claim, damages, or other liability, whether in an action of +; * contract, tort, or otherwise, arising from, out of, or in connection +; * with the software or the use or other dealings in the software. +; * +; * SUPPORT +; * Send bug reports to: <nielsen@memberwebs.com> +; */ +; +;#ifndef _RLIBERR_H_ +;#define _RLIBERR_H_ +; +;#ifndef _WINERROR_ +; #error Include winerror.h first. +;#endif +; +;#define HRESULT_FROM_RLIB(code) \ +; MAKE_HRESULT(SEVERITY_ERROR, FACILITY_RLIB, abs(code)) +; + +SeverityNames=( + Success=0x0 + Error=0x2 + ) + + +MessageIdTypedef=HRESULT +FacilityNames=( + System=0FF + Rlib=406:FACILITY_RLIB + ) + +;/* ------------------------------------------------------------------------ *\ +; Rlib Errors +;\* ------------------------------------------------------------------------ */ + +MessageId=1 +Severity=Error +Facility=Rlib +SymbolicName=RLIB_E_NOMEM +Language=English +Out of Memory. +. + +MessageId=2 +Severity=Error +Facility=Rlib +SymbolicName=RLIB_E_SYNTAX +Language=English +Rep script syntax error. +. + +MessageId=3 +Severity=Error +Facility=Rlib +SymbolicName=RLIB_E_REGEXP +Language=English +Regular expression syntax error. +. + +MessageId=4 +Severity=Error +Facility=Rlib +SymbolicName=RLIB_E_LOOP +Language=English +Rep encountered an endless loop. +. + +MessageId=5 +Severity=Error +Facility=Rlib +SymbolicName=RLIB_E_USER +Language=English +User defined error. +. + +MessageId=6 +Severity=Error +Facility=Rlib +SymbolicName=RLIB_E_IOERR +Language=English +There was an error reading or writing the data. +. + +MessageId=10 +Severity=Error +Facility=Rlib +SymbolicName=RLIB_E_INVARG +Language=English +Programmer Error: Invalid argument. +. + +;#endif // _RLIBERR_H_
\ No newline at end of file |