Reputation: 17
I added an item to a system menu in a dialg based app, item is shown in a menu, but when I click it, nothing happend. Here's the code:
#define IDM_CLIP 17
BOOL CCalculatorControlDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
CString strClip;
strClip.LoadString(IDS_CLIPBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
pSysMenu->AppendMenu(MF_STRING, IDM_CLIP, strClip);
}
}
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
m_Calculator1.SetNumFormat("%0.2f");
LOGFONT lf;
m_Calculator1.GetResultWndFont(&lf);
strcpy(lf.lfFaceName, "Brittanic Bold");
m_Calculator1.SetResultsWndFont(&lf);
m_Calculator1.GetButtonFont(&lf);
strcpy(lf.lfFaceName, "Tahoma");
m_Calculator1.SetButtonFont(&lf);
m_Calculator1.SetResultsWndBkClr(RGB(128,128,128));
m_Calculator1.SetResultsWndTxtClr(RGB(255,255,255));
return FALSE;
}
void CCalculatorControlDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else if((nID & 0xFFF0) == IDM_CLIP)
{
m_Calculator1.OnEditCopy();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
About dialog is added autommatically by the framework and I added IDM_CLIP. m_Calculator1.OnEditCopy() is function from my CCalculatorCtrl class which is coping text to clipboard. I also included CCalculatorCtrl.h file in my CalculatorControlDlg.cpp file, where I'm editing system menu. Here is OnEditCopy method, which btw works with button control...
This is the method I'm calling in CCalculatorControlDlg class.
void CCalculatorCtrl::OnEditCopy()
{
if ( !OpenClipboard() )
{
AfxMessageBox( _T("Cannot open the Clipboard") );
return;
}
// Remove the current Clipboard contents
if( !EmptyClipboard() )
{
AfxMessageBox( _T("Cannot empty the Clipboard") );
return;
}
// Get the currently selected data
HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, 64);
strcpy_s((char*)hGlob, 64, m_strCurrentEntry);
// For the appropriate data formats...
if ( ::SetClipboardData( CF_TEXT, hGlob ) == NULL )
{
CString msg;
msg.Format(_T("Unable to set Clipboard data, error: %d"), GetLastError());
AfxMessageBox( msg );
CloseClipboard();
GlobalFree(hGlob);
return;
}
AfxMessageBox( _T("Copy to clipboard successful!"));
CloseClipboard();
}
I hope I'm understandable... Thanks in advance.
Upvotes: 0
Views: 2821
Reputation: 10613
It should be fairly obvious based on the code what is happening; remember that 17
is 0x11
The problem is that when you do (nID & 0xFFF0)
the result is 0x0011 & 0xFFF0
which yields: 0x0010
.
So the solution is to fix IDM_CLIP
to have the appropriate value. As you've seen, it can't be just anything. From the MSDN page on CWnd::OnSysCommand
says: “In WM_SYSCOMMAND
messages, the four low-order bits of the nID
parameter are used internally by Windows. When an application tests the value of nID
, it must combine the value 0xFFF0 with the nID
value by using the bitwise-AND operator to obtain the correct result.”
It should be obvious based on the that the value you choose should not have any of the low 4 bits set.
Upvotes: 2
Reputation: 4557
In method
void CCalculatorControlDlg::OnSysCommand(UINT nID, LPARAM lParam)
The line
else if((nID & 0xFFF0) == IDM_CLIP)
cannot be right, you are masking 0x11 (hex for 17) against 0xfff0. The result is 16.
(nID & 0xFFF0) is never the value 17 which is IDM_CLIP.
Use another id for IDM_CLIP.
Upvotes: 3