多显示器
在系统中存在多个显示器是经常碰到的情况,如果存在,在哪个显示器上执行满屏的时候,系统不能随意把执行播放或者普通显示到首个显示器中,而是应该显示在显示界面当前的显示接口中。 以下讨论windows下MFC的多显示器支持。
先看以下代码,MFC view的视图类中,我们使用封装类CMonitor,可以获取有多少个显示器,并且得到显示的矩形窗口
int CMFCApplication3View::MonitorMonitor(RECT &rect)
{
int count = CMonitors::GetMonitorCount();
if (count > 0)
{
CMonitor monitor = CMonitors::GetNearestMonitor(this);
//RECT myrect;
monitor.GetMonitorRect(&rect);
return 0;
}
return -1;
}
下面是转换全屏的逻辑代码
void CMFCApplication3View::FullScreenToggle()
{
if (m_bFullScreen)
{
LockWindowUpdate();
HWND hWnd_ = GetSafeHwnd();
::SetParent(hWnd_, m_hWndParent);
SetWindowPlacement(&_temppl);
::SetForegroundWindow(m_hWndParent);
::SetFocus(m_hWndParent);
::SetFocus(hWnd_);
UnlockWindowUpdate();
}
else
{
WINDOWPLACEMENT wp1;
ZeroMemory(&wp1, sizeof(WINDOWPLACEMENT));
wp1.length = sizeof(WINDOWPLACEMENT);
wp1.showCmd = SW_SHOWNORMAL;
if (MonitorMonitor(wp1.rcNormalPosition) != 0)
{
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
wp1.rcNormalPosition.left = 0;
wp1.rcNormalPosition.top = 0;
wp1.rcNormalPosition.right = nScreenWidth;
wp1.rcNormalPosition.bottom = nScreenHeight;
}
HWND hWnd_ = GetSafeHwnd();
GetWindowPlacement(&_temppl);
//GetWindowPlacement(&_temppl);
m_hWndParent = ::GetParent(hWnd_);
::SetParent(hWnd_, GetDesktopWindow()->m_hWnd);
SetWindowPlacement(&wp1);
::SetForegroundWindow(GetDesktopWindow()->m_hWnd);
::SetForegroundWindow(hWnd_);
}
m_bFullScreen = !m_bFullScreen;
}
CMonitor实际上使用API函数MonitorFromWindow 来获取显示器接口。
CMonitor CMonitors::GetNearestMonitor( const CWnd* pWnd )
{
ASSERT( pWnd );
ASSERT( ::IsWindow( pWnd->m_hWnd ) );
CMonitor monitor;
monitor.Attach( ::MonitorFromWindow( pWnd->GetSafeHwnd(), MONITOR_DEFAULTTONEAREST ) );
return monitor;
}
其他API
2.1 得到显示器信息
MONITORINFO mi;
RECT rc;
mi.cbSize = sizeof( mi );
::GetMonitorInfo( m_hMonitor, &mi );
2.2 得到像素点信息技巧
int CMonitor::GetBitsPerPixel() const
{
HDC hdc = CreateDC();
int ret = ::GetDeviceCaps( hdc, BITSPIXEL ) * ::GetDeviceCaps( hdc, PLANES );
VERIFY( ::DeleteDC( hdc ) );
return ret;
}
2.3 是否是窗口
::IsWindow( pWnd->GetSafeHwnd()
IsWindow 函数非常有用,在“窗口“”还没有成为窗口的时候,我们可以用这个函数作为判断,启动过程中,窗口还没有初始化完毕,我们不能使用窗口的一些特性,否则就会造成程序崩溃
2.4 设置窗口位置 pWnd->SetWindowPos( NULL, rect.left, rect.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
这个其实就是关键API函数,要让界面全屏在哪个显示器上,无非就是计算整个显示区域,并设置窗口位置罢了。
总结无论哪个操作系统的原理都是类似的,程序代码在于理解层次和逻辑,数据结构和算法,不在于哪种操作系统和哪种语言,无论是国产化操作系统和非国产化我们都要理解原理去操作,以上API和示例,希望帮助需要帮助的人。
我是协议专家,有问题可以共同探讨。按照我的博客页面首页可以找到我。