Hiding an MFC dialog box - c++

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).

Related

Get HWND of a window i clicked on

I'm making a program, with c++ and winapi, where you can click a button, then select a window and it changes the transparency of that window.
I have no problems of making the window transparent, but i can't get the hwnd of a window.
When I use this function the program just crashes (No errors are being printed to the console).
HWND getHWND(HWND self)
{
HWND found = GetForegroundWindow();
if(found == self || found == NULL)
return getHWND(self);
return found;
}
I tried using this, but I don't like it, because the user has only 2 seconds to click on another window. (I'know I could use a bigger delay, but then it might be to much.. so this isn't optimal)
HWND getHWND()
{
Sleep(2000);
return GetForegroundWindow();
}
Don't poll for the active window, especially not with a recursive function. Just let the OS notify you when a window is clicked.
When the user clicks on your button, you can use SetCapture(), or a mouse hook via SetWindowsHookEx(), to direct subsequent mouse clicks to your app even if they are clicking on someone else's window. When you detect a click, release the capture/hook, and then use WindowFromPoint() to get the HWND at the location of the click.

How do i move parent dialog when dragging child dialog, in MFC?

Really need some help
How do I move the parent dialog when dragging the child dialog?
I have it so that when I drag the parent dialog, the child dialog is also moved, but not the reverse relationship.
Any help would be greatly appreciated, thanks!
My Main dialog.cpp:
void MainDialog::OnMove(int x, int y)
{
CDialog::OnMove(x, y);
m_pDialog->SetWindowPos(&wndTop, x, y, 50, 50, SWP_NOZORDER); // child dialog
}
BEGIN_MESSAGE_MAP(CTranslucentDialog, CDialog)
//AFX_MSG_MAP
ON_WM_ERASEBKGND()
ON_WM_MOVE()
ON_WM_SIZE()
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
Thanks, I was able to get it to work by creating a handler for NCHITTEST and returning HTTRANSPARENT.
LRESULT CGadgetStandardDialog::OnNcHitTest(CPoint point)
{
return HTTRANSPARENT;
}
The Problem is that the Mouse Input is consumed by the child. So clicking in a child window and dragging there, usually selects some data in the child (in an edit Control). Or for a static Control the mouse Input is forwarded to the parent.
So you. Need to decide... You always have the posibility to handle this in WM_NCHITTEST and return HTCAPTION, or you allow the parent to handle this in retunring HTTRANSPARENT.
BTW: If you want to implement moving a window with the mouse in the Client area too just handle WM_NCHITTEST and return HTCAPTION. there is no Need to implement a mouse movehandler and doing it by yourself.

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.

CMFCPopupMenu Stays In the Background in Win7

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!

Static control with WS_EX_TRANSPARENT style not repainted

I am trying to create a control that implements the per-pixel alpha blend while painting a 32-bit bitmap.
I extended a CWnd and use static control in the resource editor. I managed to paint the alpha channel correctly but still the static control keep painting the gray background.
I overwrote the OnEraseBkgnd to prevent the control from painting the background but it didn't worked. I finally managed to do it by using WS_EX_TRANSPARENT.
My problem now is that my control is placed over other control. The first time the dialog is painted all works fine...but if I click over the "parent" control (ie the one beneath my control) my control doesn't received the WM_PAINT message. So it is not painted anymore.
If I minimize the aplication and maximized it again the controls are painted again.
Please, can anybody give a hint? I am getting crazy with this control!!!
Thanks.
I would have though that if you are processing both the WM_ERASEBKGND and the WM_PAINT messages then you should have cover all the painting options, without having to resort to using the WS_EX_TRANSPARENT style.
Are you sure your code is not passing these messages on to the default processing?
One other option might be to subclass the static control, just to make sure your code is the only one handling these two messages.
BEGIN_MESSAGE_MAP(CTransparentStatic, CStatic)
ON_WM_ERASEBKGND()
ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()
BOOL CTransparentStatic::OnEraseBkgnd(CDC* /*pDC*/)
{
// Prevent from default background erasing.
return FALSE;
}
BOOL CTransparentStatic::PreCreateWindow(CREATESTRUCT& cs)
{
cs.dwExStyle |= WS_EX_TRANSPARENT;
return CStatic::PreCreateWindow(cs);
}
HBRUSH CTransparentStatic::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
{
pDC->SetBkMode(TRANSPARENT);
return reinterpret_cast<HBRUSH>(GetStockObject(NULL_BRUSH));
}
void CTransparentStatic::PreSubclassWindow()
{
CStatic::PreSubclassWindow();
const LONG_PTR exStyle = GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, exStyle | WS_EX_TRANSPARENT);
}