窗口置顶问题:
对于一个非模态的对话框,ATL 、或者WTL 等窗口显示时不能置顶显示。主要表现为显示时不置顶或者被其他窗口盖住。
通常设置置顶窗口的的方法为:SetWindowPos(HWND_TOPMOST, 0 , 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
SetWindowPos()只是做一个标记,调用一次即可。
如下代码可以解决问题:通常在窗口show()之后调用。
HWND hForeWnd = ::GetForegroundWindow();
DWORD dwForeID = ::GetWindowThreadProcessId(hForeWnd,NULL);
DWORD dwCurID = ::GetCurrentThreadId();
::AttachThreadInput(dwCurID,dwForeID,TRUE);
::ShowWindow(hWnd,SW_SHOWNORMAL);
::SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
::SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
::SetForegroundWindow(hWnd);
::AttachThreadInput(dwCurID,dwForeID,FALSE);
右下角弹窗:
很多软件有需要弹窗的场景,弹窗提示升级更新,弹窗广告,天窗提示天气,,,推广等等,如今的世界人类已经无法阻止泡泡了。
弹窗的位置计算方法:
获得桌面可是区域:
void _GetWorkAreaVisibleRect(OUT CRect& rcArea)
{
RECT rc;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
int nXScreen = 0;
int nYScreen = 0;
nXScreen = ::GetSystemMetrics(SM_CXSCREEN);
nYScreen = ::GetSystemMetrics(SM_CYSCREEN);
rcArea= CRect(rc);
//>自动隐藏任务栏
if (rcArea.Width() == nXScreen && rcArea.Height() == nYScreen)
{
RECT rcShell;
HWND hwndTray = NULL;
hwndTray = ::FindWindow(_T("Shell_TrayWnd"), NULL);
if (hwndTray)
{
::GetWindowRect(hwndTray, &rcShell);
CRect rcTray = CRect(rcShell);
if (nXScreen == rcTray.Width())
{
if (rcTray.bottom > nYScreen/2) ///>下
{
rcArea.bottom -= rcTray.Height();
}
else ///>上
{
rcArea.top += rcTray.Height();
}
}
else ///>左右
{
if (rcTray.left < nXScreen/2) //>左
{
rcArea.left += rcTray.Width();
}
else
{
rcArea.right -= rcTray.Width();
}
}
}
}
}
移动窗口位置函数:
void _AdjustPanelPos()
{
CRect rc;
_GetWorkAreaVisibleRect(rc);
CRect rcWin;
GetWindowRect(rcWin);
int nPos = 0;
if (rc.bottom < m_ptPopPos.y) ///>底部
{
rcWin.MoveToX(m_ptPopPos.x - rcWin.Width() / 2);
rcWin.MoveToY(rc.bottom - rcWin.Height());
nPos = 1;
}
else if (rc.right < m_ptPopPos.x) ///>右边
{
rcWin.MoveToX(rc.right - rcWin.Width());
rcWin.MoveToY(rc.bottom - rcWin.Height());
nPos = 2;
}
else if (rc.top > m_ptPopPos.y) ///>上边
{
rcWin.MoveToX(m_ptPopPos.x - rcWin.Width() / 2);
rcWin.MoveToY(rc.top);
}
else ///>左边
{
rcWin.MoveToX(rc.left);
rcWin.MoveToY(rc.bottom - rcWin.Height());
nPos = 3;
}
if (rcWin.left < rc.left)
rcWin.OffsetRect(rc.left - rcWin.left, 0);
if (rcWin.top < rc.top)
rcWin.OffsetRect(0, rc.top - rcWin.top);
if (rcWin.right > rc.right)
rcWin.OffsetRect(rc.right - rcWin.right, 0);
if (rcWin.bottom > rc.bottom)
rcWin.OffsetRect(0, rc.bottom - rcWin.bottom);
CPoint ptLT = CPoint(rcWin.left, rcWin.top);
::MoveWindow(m_hWnd, ptLT.x, ptLT.y, rcWin.Width(), rcWin.Height(), FALSE);
}
使用方法:
void Show()
{
_AdjustPopPos();
SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
ShowWindow(SW_SHOWNA);
}
我想一个有良心的泡泡应该是 不抢焦点的,不然影响用户输入或者正在玩游戏或者手正忙着。所以用了 SW_SHOWNA SWP_NOACTIVATE 这些参数。