I have a modal dialog with a list control. Right clicking one of the items in the list control, shows a content menu. Clicking this popup menu, opens another modal dialog with another list control.
My problem is that I can't display a right click content menu for the list control in the second dialog.
I tried:
void CMyListCtrl::OnContextMenu(CWnd* , CPoint point)
{
if (GetSelectedCount() == 0)
return ;
if (point.x == -1 && point.y == -1)
{
//keystroke invocation
CRect rect;
GetClientRect(rect);
ClientToScreen(rect);
point = rect.TopLeft();
point.Offset(5, 5);
}
CMenu menu;
VERIFY(menu.LoadMenu(IDR_HISTORY_MENU));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
CWnd* pWndPopupOwner = this->GetParent();
SetForegroundWindow();
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
point.x,
point.y,
pWndPopupOwner);
}
and I also added to the parent dialog ON_WM_INITMENUPOPUP
Also tried just to create a popup menu on the fly
void CHistoryListCtrl::OnContextMenu(CWnd* , CPoint point)
{
if (GetSelectedCount() == 0)
return ;
if (point.x == -1 && point.y == -1)
{
//keystroke invocation
CRect rect;
GetClientRect(rect);
ClientToScreen(rect);
point = rect.TopLeft();
point.Offset(5, 5);
}
CMenu addMenu;
addMenu.CreatePopupMenu();
// add all possible interface items
CString mstr; mstr="Compare";
addMenu.AppendMenu(MF_ENABLED | MF_STRING,ID_HISTORY_COMPARE , (LPCTSTR)mstr);
addMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this,NULL);
addMenu.DestroyMenu();
}
It didn't work as well. Tried to add SetForgroundWindow before the call to TrackPopupMenu, but it also failed.
Any idea what to do ?
Related
// CMFCApplication1Dlg dialog
CMFCApplication1Dlg::CMFCApplication1Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CMFCApplication1Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFCApplication1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplication1Dlg::OnBnClickedButton1)
END_MESSAGE_MAP()
// CMFCApplication1Dlg message handlers
BOOL CMFCApplication1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CMFCApplication1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMFCApplication1Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMFCApplication1Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CMFCApplication1Dlg::OnBnClickedButton1()
{
//Simulating the similar code as product
CFrameWnd *pFrame = GetParentFrame();
CMenu popup;
popup.CreatePopupMenu();
LPCWSTR pszMenuItem2 = L"Korean with wchar_t: 기존 운";
AppendMenuW(popup.m_hMenu, MF_STRING, 1, pszMenuItem2);
TCHAR* pszMenuItem3 = "|| Korean without wchar_t: 또는 차량 삽입";
AppendMenu(popup.m_hMenu, MF_STRING, 2, pszMenuItem3);
UINT nCmd = popup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
14, 20, pFrame, 0);
}
I have written above piece of code to generate popup menu in the screen on button click but it doesn't show any menu at all? Am I missing something?
As you asked here is the complete code. Actually I have placed one static button through GUI and on button click trying to generate the popup menu.
These button is not created dynamically. Also, the entire code here is generated by wizard except the last portion of the code about the button click.
The problem was in the handle, if I use the right API to get the handle, it shows the popup menu.
Here is the updated code.
void CMFCApplication1Dlg::OnBnClickedButton1()
{
//Simulating the similar code as product
HWND wnd= GetSafeHwnd();//<---- this had to change
CMenu popup;
popup.CreatePopupMenu();
LPCWSTR pszMenuItem2 = L"Korean with wchar_t: 기존 운";
AppendMenuW(popup.m_hMenu, MF_STRING, 1, pszMenuItem2);
TCHAR* pszMenuItem3 = "|| Korean without wchar_t: 또는 차량 삽입";
AppendMenu(popup.m_hMenu, MF_STRING, 2, pszMenuItem3);
UINT nCmd = popup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
14, 20, CWnd::FromHandle(wnd)/*need this api to get the CWnd from HWND*/, 0);
Im working on some Window Customizing stuff.
I removed title bar and border of CFrameWnd and added my own title bar.
It seems work nice.
But if I add menu to this window, menu will be on top of this window. (above my title bar)
So I add new CFrameWnd and set my menu to this new CFrameWnd.
this is the code.
CMenu * pMenu = this->GetMenu();
if( pMenu != NULL )
{
this->SetMenu(NULL);
m_pMenuWnd = new CMenuWindow();
m_pMenuWnd->Create(NULL, NULL, 0, m_WindowRects.MenuRect, this, 0, NULL);
m_pMenuWnd->SetMenu(pMenu);
m_pMenuWnd->ShowWindow(SW_NORMAL);
}
And I added this menu window's move handler on my custom CFrameWnd's OnSize, OnMove Message Handler for corrent positionning.
It looks pretty good.
But when I minimize and restore its position, menu windows position is just white blank.
But if I move cursor on there, menus r there.
What am I doing wrong?
I checked OnCtlColor but its not even get called.
Here's CMenuWindow code
BEGIN_MESSAGE_MAP(CMenuWindow, CFrameWnd)
ON_WM_CREATE()
ON_WM_ACTIVATE()
ON_WM_KEYUP()
ON_WM_SYSKEYUP()
END_MESSAGE_MAP()
void CMenuWindow::OnDraw(CDC* pDC)
{
CRect clRect;
GetClientRect(&clRect);
}
// CMenuView message handlers
int CMenuWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
ModifyStyle(WS_CAPTION, WS_CLIPCHILDREN);
ModifyStyleEx(WS_EX_CLIENTEDGE,0);
return 0;
}
I created a MFC application.Sometimes the controls(Button,Label etc) in the Dialog goes invisible at run time.The Dialog form remains.This is a random issue.The screenshots of the dialog in normal time and when goes blank are attached.Can anyone help me to find the solution for this ?
http://i.stack.imgur.com/KTDGV.png
http://i.stack.imgur.com/3PqUb.png
for displaying/hiding the Dialog i used the following code
void CVideoConverter::PopUpDlg(BOOL bValue)
{
try
{
if(bValue) // show
{
CVideoConverterApp::m_pCVideoConverterDlg->ShowWindow(SW_SHOWNORMAL);
CVideoConverterApp::m_pCVideoConverterDlg->UpdateWindow();
}
else
{// hide
CVideoConverterApp::m_pCVideoConverterDlg->ShowWindow(SW_MINIMIZE);
}
}
catch(...)
{}
}
The following code was used to position the dialog to bottom right corner of the window.This is called before the PopupDlg()
void CVideoConverter::SetWindowToBottomRightCorner()
{
try
{
CRect rcScreen;
SystemParametersInfo(SPI_GETWORKAREA, 0, (void *) &rcScreen, 0);
CRect rcWindow;
GetWindowRect(&rcWindow);
MoveWindow(rcScreen.right - rcWindow.Width(), rcScreen.bottom - rcWindow.Height(), rcWindow.Width(), rcWindow.Height(), TRUE);
}
catch(...)
{}
}
I try to draw in a static text control named IDC_RESULT.When I click the OK button, the static text will display different picture according to the shape I selected.So I declare three bool variable: isLine ,is Rect and isEllipse, everytime when I choose Lien radio box, I make the bool variabel isLine be true and the others be false, the same as Rectangle and Ellipse.
This is my code:
void CDrawDlg::OnPaint()
{
CWnd* pWnd = (CWnd*)GetDlgItem(IDC_RESULT);
CPaintDC dcPaint(pWnd);
CPen pen(PS_SOLID,2,RGB(0,0,0));
dcPaint.SelectObject(&pen);
CRect rect;
pWnd->GetClientRect(&rect);
if(isLine)
{
dcPaint.MoveTo(10,150);
dcPaint.LineTo (350,150);
}
if(isRect)
{
dcPaint.Rectangle(50, 100, 300, 200);
}
if(isEllipse)
{
doSomething;
}
ReleaseDC(&dcPaint);
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
And the function below associate with the OK button:
void CDrawDlg::OnBnClickedOk()
{
Invalidate(false);
}
The question is: How to erase the line in the static text control when I select Rectangle and click the OK button to draw a rectangle,but I can't erase the line.
The parameter to Invalidate (bErase) controls whether or not the background within the update region should be erased. Since you passed false it isn't. Pass TRUE instead.
As an aside, you should use TRUE/FALSE instead of true/false as arguments to MFC methods. Even though the types are compatible they are still different.
I know it can be done with OnCtlColor(), but it changes colors when the form is being loaded and the static texts are to be drawn, I want to do it after form is loaded, with a timer maybe, I searched for a solution but I didn't find a clear one, this is what I wrote:
void CTabFive::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CWnd* pWnd = this->GetDlgItem(IDC_Chromosome1);
CDC* dc = pWnd->GetDC();
dc->SetBkColor(RGB(200,0,0));
pWnd->Invalidate();
pWnd->UpdateWindow();
Invalidate();
UpdateWindow();
//flag = true;
}
No timer is needed. Here I have a bool m_coloured member of the class initialized to false, and toggled in the button press. The OnCtlColor will draw in red or in the system colour depending on the value of m_coloured. Works nicely.
HBRUSH Cmfcvs2010Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
if (nCtlColor == CTLCOLOR_STATIC && pWnd->GetDlgCtrlID() == IDC_LABEL)
{
DWORD d = GetSysColor(COLOR_BTNFACE);
COLORREF normal = RGB(GetRValue(d), GetGValue(d), GetBValue(d));
COLORREF red = RGB(255, 0, 0);
pDC->SetBkColor(m_coloured ? red : normal);
}
return hbr;
}
void Cmfcvs2010Dlg::OnBnClickedButton1()
{
m_coloured = !m_coloured;
Invalidate();
}