📄 mtluser.h
字号:
// Methods
void UpdateMDIFrameTitle()// no effect
{
T* pT = static_cast<T*>(this);
BOOL bMaximized = FALSE;
HWND hWndActive = pT->MDIGetActive(&bMaximized);
if (hWndActive == NULL || bMaximized == FALSE) {
return;
}
MtlSetWindowText(pT->m_hWnd, _Make_UpsideDownTitle(hWndActive));
}
// Message map and handlers
BEGIN_MSG_MAP(CMDIFrameTitleUpsideDownMessageHandler)
// MESSAGE_HANDLER(WM_GETTEXTLENGTH, OnGetTextLength) no need, cuz original buffer size is always larger.
// MESSAGE_HANDLER(WM_SETTEXT, OnSetText) never called by MDI system
MESSAGE_HANDLER(WM_GETTEXT, OnGetText)
END_MSG_MAP()
LRESULT OnGetText(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
UINT cchTextMax = (UINT)wParam; // number of characters to copy
LPTSTR lpszText = (LPTSTR)lParam;
bHandled = FALSE;
if (!m_bValid)
return 0;
T* pT = static_cast<T*>(this);
// first, find the mdi child's title
BOOL bMaximized = FALSE;
HWND hWndActive = pT->MDIGetActive(&bMaximized);
if (hWndActive == NULL || bMaximized == FALSE)
return 0;
CString strApp; strApp.LoadString(IDR_MAINFRAME);
CString strTitle = MtlGetWindowText(hWndActive) + _T(" - ") + strApp;
::lstrcpyn(lpszText, strTitle, cchTextMax);
bHandled = TRUE;
return min(strTitle.GetLength(), cchTextMax);
}
CString _Make_UpsideDownTitle(HWND hWndMDIChild)
{
CString strChild = MtlGetWindowText(hWndMDIChild);
CString strApp; strApp.LoadString(IDR_MAINFRAME);
return strChild + _T(" - ") + strApp;
}
LRESULT OnSetText(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
CString strText = (LPCTSTR)lParam;
// first, find the mdi child's title
int nFirstIndex = strText.Find(_T('['));
int nLastIndex = strText.ReverseFind(_T(']'));
if (nFirstIndex > nLastIndex || nFirstIndex == -1 || nFirstIndex == -1) {
bHandled = FALSE;
return FALSE;
}
CString strChild = strText.Mid(nFirstIndex, nLastIndex - nFirstIndex + 1);
// second, find the application's title
CString strApp; strApp.LoadString(IDR_MAINFRAME);
strText = strChild + _T(" - ") + strApp;
T* pT = static_cast<T*>(this);
return pT->DefWindowProc(uMsg, wParam, (LPARAM)(LPCTSTR)strText);
}
};
template <class T>
class CHelpMessageLine
{
public:
BEGIN_MSG_MAP(CHelpMessageLine)
MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
END_MSG_MAP()
LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
if(pT->m_hWndStatusBar == NULL)
return pT->DefWindowProc(uMsg, wParam, lParam);
HMENU hMenu = (HMENU)lParam;
WORD wFlags = HIWORD(wParam);
UINT uItem = (UINT)LOWORD(wParam); // menu item or submenu index
CString strHelp;
if(wFlags == 0xFFFF && hMenu == NULL) { // menu closing
::SendMessage(pT->m_hWndStatusBar, SB_SIMPLE, FALSE, 0L);
}
else {
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) // MDI child windows
wID = ATL_IDS_MDICHILD;
strHelp.LoadString(wID);
int nStart = strHelp.Find(_T('\t'));
int nLast = strHelp.Find(_T('\n'));
if (nStart == -1 && nLast != -1) {
strHelp = strHelp.Mid(0, nLast);
}
else if (nStart != -1 && nLast == -1) {
strHelp = strHelp.Right(strHelp.GetLength() - nStart - 1);
}
else if (nStart != -1 && nLast != -1) {
ATLASSERT(nStart < nLast);
strHelp = strHelp.Mid(nStart + 1, nLast - nStart - 1);
}
}
else // popup support
{
HMENU hMenuPopup = ::GetSubMenu(hMenu, uItem);
UINT nID = -1;
TCHAR szString[100];
// search the first non-popup menu's ID
for (int i = 0; i < ::GetMenuItemCount(hMenuPopup); ++i) {
// Fixed by Nisizawa@mcomp.co.jp, thanks.
// Note. GetMenuItemInfo often change mii.dwTypeData.
// even if the API reference says not.
CMenuItemInfo mii;
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU;
mii.dwTypeData = szString;
mii.cch = 100;
if (!::GetMenuItemInfo(hMenuPopup, i, TRUE, &mii))
continue;
bool bSkip = _check_flag(MFT_SEPARATOR, mii.fType) || mii.hSubMenu != NULL;
nID = bSkip ? -1 : mii.wID;
if (nID != -1) {
if (nID >= ID_FILE_MRU_FIRST && nID <= ID_FILE_MRU_LAST) // MRU items
nID = ATL_IDS_MRU_FILE;
else if (nID >= ATL_IDM_FIRST_MDICHILD) // MDI child windows
nID = ATL_IDS_MDICHILD;
break;
}
}
if (nID != -1) {
strHelp.LoadString(nID);
int nIndex = strHelp.Find(_T('\t'));
if (nIndex != -1) {
strHelp = strHelp.Left(nIndex);
}
else {
strHelp.Empty();
}
}
}
::SendMessage(pT->m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
::SendMessage(pT->m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)(LPCTSTR)strHelp);
}
return pT->DefWindowProc(uMsg, wParam, lParam);
}
};
/////////////////////////////////////////////////////////////////////////////
// CInitDialogImpl - property page that supports DropDownList initialization
#ifndef _ATL_RT_DLGINIT
#define _ATL_RT_DLGINIT MAKEINTRESOURCE(240)
#endif
template <class T, class TBase = CWindow>
class ATL_NO_VTABLE CInitDialogImpl : public CDialogImpl< T, TBase >
{
public:
typedef CInitDialogImpl< T, TBase > thisClass;
typedef CDialogImpl< T, TBase > baseClass;
// Data members
HGLOBAL m_hInitData;
// Constructor/destructor
CInitDialogImpl() : m_hInitData(NULL)
{
T* pT = static_cast<T*>(this);
pT; // avoid level 4 warning
HINSTANCE hInstance = _Module.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);
if(hDlgInit != NULL)
{
m_hInitData = ::LoadResource(hInstance, hDlgInit);
}
}
else
{
ATLASSERT(FALSE && _T("CInitDialogImpl - Cannot find dialog template!"));
}
}
~CInitDialogImpl()
{
if(m_hInitData != NULL)
{
UnlockResource(m_hInitData);
::FreeResource(m_hInitData);
}
}
// Methods
bool ExecuteDlgInit()
{
BYTE* pInitData = (BYTE*)::LockResource(m_hInitData);
return _ExecuteDlgInit(pInitData);
}
bool _ExecuteDlgInit(LPVOID lpResource)
{// cf.MFC
bool bSuccess = true;
if (lpResource != NULL)
{
UNALIGNED WORD* lpnRes = (WORD*)lpResource;
while (bSuccess && *lpnRes != 0)
{
WORD nIDC = *lpnRes++;
WORD nMsg = *lpnRes++;
DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
// In Win32 the WM_ messages have changed. They have
// to be translated from the 32-bit values to 16-bit
// values here.
#define WIN16_LB_ADDSTRING 0x0401
#define WIN16_CB_ADDSTRING 0x0403
#define AFX_CB_ADDSTRING 0x1234
// unfortunately, WIN16_CB_ADDSTRING == CBEM_INSERTITEM
if (nMsg == AFX_CB_ADDSTRING)
nMsg = CBEM_INSERTITEM;
else if (nMsg == WIN16_LB_ADDSTRING)
nMsg = LB_ADDSTRING;
else if (nMsg == WIN16_CB_ADDSTRING)
nMsg = CB_ADDSTRING;
// check for invalid/unknown message types
ATLASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
nMsg == CBEM_INSERTITEM);
#ifdef _DEBUG
// For AddStrings, the count must exactly delimit the
// string, including the NULL termination. This check
// will not catch all mal-formed ADDSTRINGs, but will
// catch some.
if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING || nMsg == CBEM_INSERTITEM)
ATLASSERT(*((LPBYTE)lpnRes + (UINT)dwLen - 1) == 0);
#endif
if (nMsg == CBEM_INSERTITEM)
{
USES_CONVERSION;
COMBOBOXEXITEM item;
item.mask = CBEIF_TEXT;
item.iItem = -1;
item.pszText = A2T(LPSTR(lpnRes));
if (::SendDlgItemMessage(m_hWnd, nIDC, nMsg, 0, (LPARAM) &item) == -1)
bSuccess = false;
}
else if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING)
{
// List/Combobox returns -1 for error
if (::SendDlgItemMessageA(m_hWnd, nIDC, nMsg, 0, (LPARAM) lpnRes) == -1)
bSuccess = false;
}
// skip past data
lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
}
}
// send update message to all controls after all other siblings loaded
// if (bSuccess)
// SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, FALSE, FALSE);
return bSuccess;
}
// DDX methods
void DDX_CBIndex(UINT nID, int& nValue, BOOL bSave)
{
HWND hWndCtrl = GetDlgItem(nID);
ATLASSERT(::IsWindow(hWndCtrl));
if(bSave)
{
nValue = (int)::SendMessage(hWndCtrl, CB_GETCURSEL, 0, 0L);
ATLASSERT(nValue >= 0 && nValue < (int)::SendMessage(hWndCtrl, CB_GETCOUNT, 0, 0L));
}
else
{
if(nValue < 0 || nValue >= (int)::SendMessage(hWndCtrl, CB_GETCOUNT, 0, 0L))
{
ATLTRACE2(atlTraceUI, 0, "ATL: Warning - dialog data combobox value (%d) out of range.\n", nValue);
nValue = 0; // default to off
}
int nRet = ::SendMessage(hWndCtrl, CB_SETCURSEL, nValue, 0L);
ATLASSERT(nRet != CB_ERR);
}
}
};
/////////////////////////////////////////////////////////////////////////////
// CInitPropertyPageImpl - property page that supports DropDownList initialization
// That is, the subset of CAxProtertyPageImpl
// If you use combobox ex, don't miss ICC_USEREX_CLASSES.
#define DDX_CBINDEX(nID, var) \
if(nCtlID == (UINT)-1 || nCtlID == nID) \
DDX_CBIndex(nID, var, bSaveAndValidate);
template <class T, class TBase = CPropertyPageWindow>
class ATL_NO_VTABLE CInitPropertyPageImpl : public CPropertyPageImpl< T, TBase >
{
public:
typedef CInitPropertyPageImpl< T, TBase > thisClass;
typedef CPropertyPageImpl< T, TBase > baseClass;
// Data members
HGLOBAL m_hInitData;
// Constructor/destructor
CInitPropertyPageImpl(_U_STRINGorID title = (LPCTSTR)NULL) :
CPropertyPageImpl< T, TBase >(title),
m_hInitData(NULL)
{
T* pT = static_cast<T*>(this);
pT; // avoid level 4 warning
HINSTANCE hInstance = _Module.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);
if(hDlgInit != NULL)
{
m_hInitData = ::LoadResource(hInstance, hDlgInit);
}
}
else
{
ATLASSERT(FALSE && _T("CInitPropertyPageImpl - Cannot find dialog template!"));
}
}
~CInitPropertyPageImpl()
{
if(m_hInitData != NULL)
{
UnlockResource(m_hInitData);
::FreeResource(m_hInitData);
}
}
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)
{
bHandled = FALSE;
BYTE* pInitData = (BYTE*)::LockResource(m_hInitData);
ExecuteDlgInit(pInitData);
return TRUE;
}
// Methods
bool ExecuteDlgInit(LPVOID lpResource)
{// cf.MFC
bool bSuccess = true;
if (lpResource != NULL)
{
UNALIGNED WORD* lpnRes = (WORD*)lpResource;
while (bSuccess && *lpnRes != 0)
{
WORD nIDC = *lpnRes++;
WORD nMsg = *lpnRes++;
DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
// In Win32 the WM_ messages have changed. They have
// to be translated from the 32-bit values to 16-bit
// values here.
#define WIN16_LB_ADDSTRING 0x0401
#define WIN16_CB_ADDSTRING 0x0403
#define AFX_CB_ADDSTRING 0x1234
// unfortunately, WIN16_CB_ADDSTRING == CBEM_INSERTITEM
if (nMsg == AFX_CB_ADDSTRING)
nMsg = CBEM_INSERTITEM;
else if (nMsg == WIN16_LB_ADDSTRING)
nMsg = LB_ADDSTRING;
else if (nMsg == WIN16_CB_ADDSTRING)
nMsg = CB_ADDSTRING;
// check for invalid/unknown message types
ATLASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
nMsg == CBEM_INSERTITEM);
#ifdef _DEBUG
// For AddStrings, the count must exactly delimit the
// string, including the NULL termination. This check
// will not catch all mal-formed ADDSTRINGs, but will
// catch some.
if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING || nMsg == CBEM_INSERTITEM)
ATLASSERT(*((LPBYTE)lpnRes + (UINT)dwLen - 1) == 0);
#endif
if (nMsg == CBEM_INSERTITEM)
{
USES_CONVERSION;
COMBOBOXEXITEM item;
item.mask = CBEIF_TEXT;
item.iItem = -1;
item.pszText = A2T(LPSTR(lpnRes));
if (::SendDlgItemMessage(m_hWnd, nIDC, nMsg, 0, (LPARAM) &item) == -1)
bSuccess = false;
}
else if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING)
{
// List/Combobox returns -1 for error
if (::SendDlgItemMessageA(m_hWnd, nIDC, nMsg, 0, (LPARAM) lpnRes) == -1)
bSuccess = false;
}
// skip past data
lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
}
}
// send update message to all controls after all other siblings loaded
// if (bSuccess)
// SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, FALSE, FALSE);
return bSuccess;
}
// DDX methods
void DDX_CBIndex(UINT nID, int& nValue, BOOL bSave)
{
HWND hWndCtrl = GetDlgItem(nID);
if(bSave)
{
nValue = (int)::SendMessage(hWndCtrl, CB_GETCURSEL, 0, 0L);
ATLASSERT(nValue >= 0 && nValue < (int)::SendMessage(hWndCtrl, CB_GETCOUNT, 0, 0L));
}
else
{
if(nValue < 0 || nValue >= (int)::SendMessage(hWndCtrl, CB_GETCOUNT, 0, 0L))
{
ATLTRACE2(atlTraceUI, 0, "ATL: Warning - dialog data combobox value (%d) out of range.\n", nValue);
nValue = 0; // default to off
}
::SendMessage(hWndCtrl, CB_SETCURSEL, nValue, 0L);
}
}
};
/////////////////////////////////////////////////////////////////////////////
// WTL forgot to center a sheet...
class CCenterPropertySheet : public CPropertySheetImpl<CCenterPropertySheet>
{
public:
bool m_bCentered;
CCenterPropertySheet(_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
: CPropertySheetImpl<CCenterPropertySheet>(title, uStartPage, hWndParent), m_bCentered(false)
{ }
BEGIN_MSG_MAP(CCenterPropertySheet)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_COMMAND, CPropertySheetImpl<CCenterPropertySheet>::OnCommand)
END_MSG_MAP()
LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if (!m_bCentered) {
// now center the property sheet
CenterWindow(GetParent());
m_bCentered = true;
}
return 0;
}
};
/////////////////////////////////////////////////////////////////////////////
// menu helper
inline int MtlGetCmdIDFromAccessKey(CMenuHandle menu, const CString& strAccess, bool bFromBottom = true)
{
int nID = -1;
CString strItem;
if (bFromBottom)
{
for (int i = menu.GetMenuItemCount() - 1; i >= 0 ; --i)
{
if (menu.GetMenuString(i, strItem, MF_BYPOSITION) == 0)
continue;
if (strItem.Find(strAccess) != -1) {
nID = menu.GetMenuItemID(i);
break;
}
}
}
else
{
for (int i = 0; i < menu.GetMenuItemCount(); ++i)
{
if (menu.GetMenuString(i, strItem, MF_BYPOSITION) == 0)
continue;
if (strItem.Find(strAccess) != -1) {
nID = menu.GetMenuItemID(i);
break;
}
}
}
return nID;
}
/////////////////////////////////////////////////////////////////////////////
} //namespace MTL
#endif // __MTLUSER_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -