以下这段程序来自于著名的任务栏网速插件程序TrafficMonitor中,可以参考思路
bool CTaskBarDlg::AdjustWindowPos()
{
if (this->GetSafeHwnd() == NULL || !IsWindow(this->GetSafeHwnd()))
return false;
CRect rcMin, rcBar, rcBarSnap;
::GetWindowRect(m_hMin, rcMin); //获得最小化窗口的区域
::GetWindowRect(m_hBar, rcBar); //获得二级容器的区域
if (theApp.m_win_version.IsWindows11OrLater()) {
::GetWindowRect(m_hBarSnap, rcBarSnap); //获得二级容器(Win11)的区域
}
static bool last_taskbar_on_top_or_bottom;
CheckTaskbarOnTopOrBottom();
if (m_taskbar_on_top_or_bottom != last_taskbar_on_top_or_bottom)
{
CalculateWindowSize();
last_taskbar_on_top_or_bottom = m_taskbar_on_top_or_bottom;
}
if (m_taskbar_on_top_or_bottom) //当任务栏在桌面顶部或底部时
{
//设置窗口大小
m_rect.right = m_rect.left + m_window_width;
m_rect.bottom = m_rect.top + m_window_height;
if (rcMin.Width() != m_min_bar_width) //如果最小化窗口的宽度改变了,重新设置任务栏窗口的位置
{
m_left_space = rcMin.left - rcBar.left;
m_rcMin = rcMin;
m_min_bar_width = m_rcMin.Width() - m_rect.Width(); //保存最小化窗口宽度
if (!theApp.m_taskbar_data.tbar_wnd_on_left)
{
if (theApp.m_win_version.IsWindows11OrLater()) { //Win11兼容
if (!theApp.m_taskbar_data.tbar_wnd_snap) {
m_left_space = rcBar.right; //显示在最右侧
}
else
{
m_left_space = rcBarSnap.left - theApp.DPI(90); //贴靠在任务栏左侧(向左偏移90,防止挡住Win徽标)
}
}
::MoveWindow(m_hMin, m_left_space, 0, m_rcMin.Width() - m_rect.Width(), m_rcMin.Height(), TRUE); //设置最小化窗口的位置
m_rect.MoveToX(m_left_space + m_rcMin.Width() - m_rect.Width() + 2);
}
else
{
if (theApp.m_win_version.IsWindows11OrLater()) { //Win11兼容
if (!theApp.m_taskbar_data.tbar_wnd_snap) {
m_left_space = 0; //显示在最左侧
}
else
{
m_left_space = rcBarSnap.right; //贴靠在任务栏右侧
}
}
::MoveWindow(m_hMin, m_left_space + m_rect.Width(), 0, m_rcMin.Width() - m_rect.Width(), m_rcMin.Height(), TRUE);
m_rect.MoveToX(m_left_space);
}
m_rect.MoveToY((rcBar.Height() - m_rect.Height()) / 2);
if (theApp.m_taskbar_data.horizontal_arrange && theApp.m_win_version.IsWindows7())
m_rect.MoveToY(m_rect.top + theApp.DPI(1));
MoveWindow(m_rect);
}
}
else //当任务栏在屏幕在左侧或右侧时
{
//设置窗口大小
if (rcMin.Height() != m_min_bar_height) //如果最小化窗口的高度改变了,重新设置任务栏窗口的位置
{
m_top_space = rcMin.top - rcBar.top;
m_rcMin = rcMin;
m_min_bar_height = m_rcMin.Height() - m_rect.Height(); //保存最小化窗口高度
if (!theApp.m_taskbar_data.tbar_wnd_on_left)
{
::MoveWindow(m_hMin, 0, m_top_space, m_rcMin.Width(), m_rcMin.Height() - m_rect.Height(), TRUE); //设置最小化窗口的位置
m_rect.MoveToY(m_top_space + m_rcMin.Height() - m_rect.Height() + 2);
}
else
{
::MoveWindow(m_hMin, 0, m_top_space + m_rect.Height(), m_rcMin.Width(), m_rcMin.Height() - m_rect.Height(), TRUE); //设置最小化窗口的位置
m_rect.MoveToY(m_top_space);
}
m_rect.MoveToX((m_rcMin.Width() - m_window_width) / 2);
if (m_rect.left < theApp.DPI(2))
m_rect.MoveToX(theApp.DPI(2));
MoveWindow(m_rect);
}
}
CRect rect{ m_rect };
//如果窗口没有被成功嵌入到任务栏,窗口移动到了基于屏幕左上角的绝对位置,则修正窗口的位置
if (m_connot_insert_to_task_bar)
{
rect.MoveToXY(rect.left + rcBar.left, rect.top + rcBar.top);
this->MoveWindow(rect);
}
if (m_connot_insert_to_task_bar && ::GetForegroundWindow() == m_hTaskbar) //在窗口无法嵌入任务栏时,如果焦点设置在了任务栏上,则让窗口置顶
{
SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); //设置置顶
}
return true;
}
void CTaskBarDlg::ApplyWindowTransparentColor()
{
#ifndef COMPILE_FOR_WINXP
if (theApp.m_taskbar_data.transparent_color != 0 && theApp.m_taksbar_transparent_color_enable)
{
SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(theApp.m_taskbar_data.transparent_color, 0, LWA_COLORKEY);
}
else
{
SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
}
#endif // !COMPILE_FOR_WINXP
}