CMFCPopupMenu Stays In the Background in Win7 - c++

I'm trying some of the new MFC functionality and i want the same thing that the TrayMenu project from Visual C++ Language Samples for Visual Studio 2010 does but in my machine (don't know if is only in my machine i try to find the same problem in the web but didn't find any similar report!!!) the menu appears in the background of the new win7 traynotifywwnd, and i can't seem to put it work right:
The code is simple:
void CTrayMenuDlg::OnTrayContextMenu ()
{
CPoint point;
::GetCursorPos (&point);
CMenu menu;
menu.LoadMenu (IDR_MENU1);
CMFCPopupMenu::SetForceShadow (TRUE);
HMENU hMenu = menu.GetSubMenu (0)->Detach ();
CMFCPopupMenu* pMenu = theApp.GetContextMenuManager()->ShowPopupMenu(hMenu, point.x, point.y, this, TRUE);
pMenu->SetForegroundWindow ();
}
I think that SetForegroundWindow is some how a fix for this problem, but it does not work, it stills show bewind the window where all the tray icon are hidden and displayed when we click in the little arrow (note that if the icon is displayed in the ToolbarWindow32 -not hidden - and we call the tray context menu then it all works fine, this problem only appear if the icon is hidden and is show using the little arrow in the ToolbarWindow32 and a window is displayed with the hidden icons - is this window that stays in front of my context menu...)
Has anyone find this problem? and there is any solution for this problem?
Thanks

I am not sure about this one but you can try adding:
// Set window position to topmost window.
pMenu->SetWindowPos(
&CWnd::wndTopMost,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE );
instead of pMenu->SetForegroundWindow ();

From MSDN:
Add ::SetWindowPos(pMenu->m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE);
before the pMenu->SetForegroundWindow ();
in CTrayMenuDlg::OnTrayContextMenu () function.
For me this worked!

Related

Maximized WS_POPUP window goes in front of the taskbar

I'm creating a window in C++ with that code:
HWnd = CreateWindow(wc.lpszClassName,
"myapp",
WS_POPUP |WS_VISIBLE,
10, 10, 1000, 800, 0, 0, hInst, NULL);
It appears as I want but when I maximize it with like this:
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
then it's like a fullscreen window so that the taskbar is hidden.
I think it's because it is a POPUP window but this is like I want it to appear.
Do I need to create my own maximize function or is there a parameter to avoid that ?
Thanks
You can add WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX style.
If you want your window to be without caption then you will need to adjust window size manually to fit into desktop work area that you can query using SystemParametersInfo specifying SPI_GETWORKAREA flag.
This is a feature where the Taskbar will get out of your full-screen application:
If you want to create a fullscreen window that covers the taskbar, just create a fullscreen window and the taskbar will automatically get out of the way.
I’ve seen people hunt for the taskbar window and then do a ShowWindow(hwndTaskbar, SW_HIDE) on it. This is nuts for many reasons.
Don’t do any of this messing with the taskbar. Just create your fullscreen window and let the taskbar do its thing automatically.
Since this is Stackoverflow, a combination of Wikipedia and Reddit, i want this relevant information saved for the next guy asking this question.

c++ MFC Window(Frame) Manipulation

I'm working on an Windows Application which has to show an overlaying fixed positioned window ("PopUp") in the left corner of the MainFrame which will receive some Information if a user missed some input or if certain actions have been successfully.
The "PopUp" Titlebar shall have an Icon next to the Title (e.g. ->Icon<- "Error") and the standard X - Close-Button. The ClientArea will have an descriptive text of the occurred Message.
Additionally the standard Border of the PopUp shall be set to 1px(smaller than the default windows border)
The "PopUp" is derived from CWnd and created with WS_VISLBE | WS_CLIPSIBLINGS | WS_CHILD | WS_CAPTION in the OnCreate-Method of the Applications MainFrame Window
Now I need to set/shrink the default Border of my PopUp and add the Icon to the Titlebar of the PopUp.
Can someone give me some example code of how i can solve my issues?
I'm pretty new to c++ and MFC so far my research brought me to https://msdn.microsoft.com/en-us/library/windows/desktop/bb688195(v=vs.85).aspx
but i dont know where and how to use DwmExtendFrameIntoClientArea() but so far I've read I assume Dwm is the way to go to be able to solve both problems or is there another/totally different way? Am I on the right track?
Finally I was able to shrinkthe default Windows Border by overriding the handling of WM_NCCALCSIZE.
I will update this answer as soon as I solved how to put my Icon in the Titlebar.
As of now I'll explain how I shrink the windows border:
Add ON_WM_NCCALCSIZE() to your MessageMap of the desired Window and Implement OnNcCalcSize() (Class Wizard will help to set this up) as followed:
void YourCWndClass::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
if (bCalcValidRects){
CRect rcClient, rcWind;
GetClientRect(&rcClient);
GetWindowRect(&rcWind);
int border = (rcWind.right - rcWind.left - rcClient.right) / 2 - 1;
//-1: leaves 1px of the Windows Default Border Width erase to have no border
lpncsp->rgrc->left -= border;
lpncsp->rgrc->right += border;
lpncsp->rgrc->bottom += border;
}
CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
}
The WM_NCCALCSIZE Message is sent up on the Window Creation (when you call Create()/CreateEx() ) but at this point of time GetClientRect() and GetWindowRect() will not return the proper values therefore you need to check the Bool Parameter!!!
To trigger another WM_NCCALCSIZE to be able to work with the proper Window Rectangles call SetWindowPos() right after the window creation
if (!m_MessagePopOver->Create(NULL, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CAPTION, rect, this, NULL, NULL)){
TRACE0("failed to create MessagePopOver");
}
m_MessagePopOver->SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
This will result in a window like this:

Application in C++ with two windows. One window shown in taskbar. The other not shown

I am doing some analysis before coding and I was having some trouble finding information or implementations where there is an application where there are these characteristics:
Window #1 (shown on taskbar)
Window #2 (doesn't show on taskbar and you can put this one behind Window #1, so we are not talking about popups/dialogs rooted from Window #1)
Both Window #1 and Window #2 are in the same Project (or application, so to speak)
Again, this is just speaking conceptually, so if you can point me to some information proving that this is possible, it would be great. Note, this is in C++ not C#.
The closest I came up with is this:
Added a class derived from CWnd
Added the following function to the class
void Create2ndWindow(CWnd* pParent){
LPCTSTR pszClassName = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH) ::GetStockObject(WHITE_BRUSH), ::LoadIcon(NULL, IDI_APPLICATION));
BOOL bCreated = CreateEx(WS_EX_CLIENTEDGE,
pszClassName,
_T("My Second Window"),
WS_BORDER|WS_CAPTION|WS_ACTIVECAPTION|WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_POPUPWINDOW|WS_SIZEBOX,
CRect(20, 20, 100, 100),
pParent,
NULL);
if(bCreated)
ShowWindow(SW_SHOW);
}
In the InitInstance i added the following lines:
CSecondWindow* pWnd = new CSecondWindow();
pWnd->Create2ndWindow(pFrame);
Execute the application, 2 Windows appear on your desktop but you should see only one taskbar button for the pFrame window and no button for the CSecondWindow
if the pParent is NULL then you would see the taskbar button. There is another style you can add WS_EX_TOOLWINDOW but that reduces the height of caption bar.

Placing a Tray menu over (above) taskbar

I'm having troubles showing my tray menu above the taskbar. It doesn't matter what I specify as y-position, it only gets against the taskbar at best. The tray menu is a resource.
This is the code I'm using for a rightclick on the systrayicon:
// The message loop
case WM_RBUTTONUP:
{
CPoint point;
::GetCursorPos(&point);
CMenu menu;
menu.LoadMenu(IDR_MENU1);
HMENU hMenu = menu.GetSubMenu(0)->Detach();
CMFCPopupMenu* pMenu = theApp.GetContextMenuManager()->ShowPopupMenu(hMenu, point.x-5, point.y, this, TRUE);
pMenu->SetForegroundWindow();
break;
}
Indeed RecalcLayout makes sure that a popup is displayed within monitor's working area (not obscuring taskbar.
But there is nothing to prevent you to override this behavior.
The difference between a Windows’ menu and CMFCPopupMenu is that the menu is a window that is created by the OS and CMFCPopupMenu is a frame window that mimics the behavior of the menu.
You were almost there but you missed the fact that SetForegroundWindow does not move window, it merely changes Z-order.
I personally do not see any advantage of doing it. However, as I say nothing is impossible to achieve.
Do following if you really want to do it against advice:
CMFCPopupMenu* pMFCMenu = pCntxtMgr->ShowPopupMenu(hMenu, ptClick.x, ptClick.y, AfxGetMainWnd());
CRect rectMenu;
pMFCMenu->GetWindowRect(rectMenu);
pMFCMenu->SetWindowPos(&CWnd::wndTopMost, rectMenu.left, rectMenu.top + 25, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
25 is just an arbitrary number I used for demo purpose. You will have to calculate it to prevent menu bottom appearing off the screen.

Hiding an MFC dialog box

Ok so I am using this code to hide the taskbar icon of a dialog based MFC application(VC++). The taskbar icon and the dialog box hide whenever I click on the cross or the close buttons. But I can’t get this one thing right. Whenever I hit the close or the cross button from title bar, the dialog box first flickers and shows a sort of intermediate dialog box and then hides. This is very annoying. I am posting my code here after two days of vain effort. So guys please help me. Thanks in advance.
void CMyAppDlg::OnBnClickedCancel()
{
// TODO: Add your control notification handler code here
CWnd* pWnd;
pWnd = AfxGetMainWnd();
RemoveTaskbarIcon(pWnd);
pWnd->ModifyStyle(WS_VISIBLE, 0);
mVisible = FALSE;
}
BOOL CMyAppDlg::RemoveTaskbarIcon(CWnd* pWnd)
{
LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);
// Create static invisible window
if (!::IsWindow(mWndInvisible.m_hWnd))
{
if (!mWndInvisible.CreateEx(0, pstrOwnerClass, _T(""),
WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL, 0))
return FALSE;
}
pWnd->SetParent(&mWndInvisible);
return TRUE;
}
Here are the screen shots of dialog box. When I press the close or cross button, the dialog box which looks like this in the first place turns into this for like less than half a second and then disappears (hides).
If you show your dialog using CDialog::DoModal() the framework will make sure your dialog is shown. There is only one way to prevent a modal dialog from being shown:
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_WM_WINDOWPOSCHANGING()
END_MESSAGE_MAP()
BOOL CHiddenDialog::OnInitDialog()
{
CDialog::OnInitDialog();
m_visible = FALSE;
return TRUE;
}
void CHiddenDialog::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
if (!m_visible)
lpwndpos->flags &= ~SWP_SHOWWINDOW;
CDialog::OnWindowPosChanging(lpwndpos);
}
I think Paul DiLascia recommended the following. This is for modal dialogs only.
The following code can be put in OnInitDialog to move the dialog off-screen. You will need to implement a method for moving it back on-screen when appropriate.
CRect DialogRect;
GetWindowRect(&DialogRect);
int DialogWidth = DialogRect.Width();
int DialogHeight = DialogRect.Height();
MoveWindow(0-DialogWidth, 0-DialogHeight, DialogWidth, DialogHeight);
The answer from l33t looks good and is probably better but this is an alternative.
Maybe an obvious thing, but what happens when you do the hide before you reparent the dialog? Also what if you don't directly modify the window style but use ShowWindow(SW_HIDE)?
Finally, have you tried switching the dialog's window style to WS_CHILD before calling SetParent() and/or maybe moving it out of the client area so that the window isn't shown any more (MoveWindow(-1000, -1000) or something like that).