ATL中实现全屏切换的方法

李国帅 2009年,用于实现播放控件全屏切换,并重新计算播放小窗口。一个大窗口有最多8×8个子窗口。

实现程序全屏幕显示的思路有很多种,最常见的一种就是:

1)存储全屏显示前视图和主框架窗口在屏幕上的位置和显示信息

利用Windows API提供的一个结构体WINDOWPLACEMENT来存储全屏显示前视图和主框架窗口在屏幕上的位置和显示信息、非客户区窗口的显隐信息,以便全屏幕显示时恢复窗口原状;

GetWindowRect(&m_NormalRect);//获取当前窗口的位置
POINT pt1,pt2;
pt1.x = m_NormalRect.left;
pt1.y = m_NormalRect.top;
::ScreenToClient(GetParent(), &pt1);
pt2.x = m_NormalRect.right;
pt2.y = m_NormalRect.bottom;
::ScreenToClient(GetParent(), &pt2);
WidthRect = pt2.x - pt1.x;
HeightRect = pt2.y - pt1.y;

/* Change window style, no borders and no title bar Maximize window */
RECT rc;//获取父窗口的大小和位置
rc.left = rc.top = 0;
rc.right = GetSystemMetrics(SM_CXSCREEN);
rc.bottom = GetSystemMetrics( SM_CYSCREEN );

2)通过API函数GetDesktopWindow()得到桌面窗口,由GetWindowRect()得到显示器的尺寸;

HWND hDesktop=::GetDesktopWindow(); //
if (hDesktop == NULL)
{
ATLTRACE2("Set Parent Window To Desktop Faild\n");
m_bFullScreen = !m_bFullScreen;
return 0;
}
//改变窗口大小并置顶
SetParent(hDesktop);//atl

3)通过AdjustWindowRect()来计算当客户区大小为屏幕大小时相应的窗口大小;

4)通过SetWindowPlacement()来设置视图窗口和主窗口为客户区大小和屏幕大小的窗口;

//进入全屏显示状态
WINDOWPLACEMENT wndpl;
wndpl.length=sizeof(WINDOWPLACEMENT);
wndpl.flags=0;
wndpl.showCmd=SW_SHOWNORMAL;
wndpl.rcNormalPosition=rc;
SetWindowPlacement(&wndpl);

或者

BOOL bChangeSize = FALSE;

bChangeSize = SetWindowPos( HWND_TOPMOST, CtrlRect.left, CtrlRect.top, (CtrlRect.right - CtrlRect.left), (CtrlRect.bottom - CtrlRect.top),
SWP_SHOWWINDOW | SWP_FRAMECHANGED);////SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED))
if (!bChangeSize)
{
bChangeSize = MoveWindow(CtrlRect.left, CtrlRect.top, CtrlRect.right - CtrlRect.left, CtrlRect.bottom - CtrlRect.top);
}

5)处理窗口消息WM_GETMINMAXINFO,使窗口能够顺利的最大、最小化。

但是用这种方法并没有实现真正的全屏,好像VC6的全屏也是这样做的。如果有多屏显卡,这样实现的全屏是可以

从别的屏幕对其进行放大缩小的。


例程

LRESULT CALLBACK ScreenWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc(hWnd, message, wParam, lParam);
}

 void CTopseePlayer::CreateScreenWnd(RECT rcWnd)
{
    if(m_hWndScreen == NULL)
    {
        WNDCLASS wc;
        wc.style = 0;
        wc.lpfnWndProc = ScreenWndProc;
        wc.cbClsExtra = wc.cbWndExtra = 0;
        wc.hInstance = (HINSTANCE)NULL;
        wc.hIcon = NULL;
        wc.hCursor = NULL;
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);;
        wc.lpszMenuName = NULL;
        wc.lpszClassName = _T("ScreenWnd");

        if (::FindWindow(_T("ScreenWnd"),NULL) == NULL)
        {
            RegisterClass(&wc);
        }

        TCHAR WindowName[100];
        _tcscpy_s(WindowName,100,_T(""));
        srand((unsigned)time( NULL ));
        int ID = rand() & 0xfff;
        _stprintf_s(WindowName,_T("ScreenWnd%d"),ID);
        //HWND hw = ::FindWindow(_T("ScreenWnd"),WindowName);
        while (::FindWindow(_T("ScreenWnd"),WindowName) != NULL)
        {
            ID = rand() & 0xfff;
            _stprintf_s(WindowName,_T("ScreenWnd%d"),ID);
        }

        HWND hDesktop= NULL;//::GetDesktopWindow();
        const DWORD nostyle=WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_POPUP|WS_MAXIMIZE;
        m_hWndScreen = ::CreateWindow(wc.lpszClassName, WindowName,nostyle, rcWnd.left, rcWnd.top,rcWnd.right, rcWnd.bottom, hDesktop,NULL,NULL,NULL);
        DWORD Errno = GetLastError();
        ATLASSERT(m_hWndScreen != NULL);

        return;
    }
}
LRESULT CTopseePlayer::OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    // TODO://双击进行全屏处理

    static BOOL m_bFullScreen = FALSE;
    static RECT m_NormalRect;
    static LONG WidthRect = 0;
    static LONG HeightRect = 0;

    if (m_hWnd == NULL)
    {
        ATLTRACE2("Impossible State Wnd is Null\n");
        return 0;
    }
    CreateScreenWnd(m_rcScreen);

    BOOL bChangeSize = FALSE;
    m_bFullScreen = !m_bFullScreen;//标志切换
    if( m_bFullScreen )
    {

        RECT CtrlRect;
        GetWindowRect(&CtrlRect);//获取当前窗口的位置
        POINT pt1,pt2;
        pt1.x = CtrlRect.left;
        pt1.y = CtrlRect.top;
        ::ScreenToClient(GetParent(), &pt1);
        pt2.x = CtrlRect.right;
        pt2.y = CtrlRect.bottom;
        ::ScreenToClient(GetParent(), &pt2);
        WidthRect = pt2.x - pt1.x;
        HeightRect = pt2.y - pt1.y;
        SetRect(&m_NormalRect,0,0,WidthRect,HeightRect);

         ::ShowWindow(m_hWndScreen,SW_HIDE);
        SetParent(m_hWndScreen);//atl
        //::MoveWindow(m_hWndScreen,m_rcScreen.left+1, m_rcScreen.top+1, m_rcScreen.right - m_rcScreen.left-2, m_rcScreen.bottom - m_rcScreen.top-2,FALSE);
        SetPlayWindowRect(m_rcScreen,&bChangeSize);//改变窗口大小并置顶
        //::InvalidateRect(m_hWndScreen,&m_rcScreen,TRUE);
        if (!bChangeSize)
        {
            ATLTRACE2("SetWindowPos\n");
            SetParent(m_hOldWndParent);
            m_bFullScreen = !m_bFullScreen;
            return 0;
        }
        ::ShowWindow(m_hWndScreen,SW_SHOW);
    }
    else
    {
        SetParent(m_hOldWndParent);
        //::MoveWindow(m_hOldWndParent,m_NormalRect.left+1, m_NormalRect.top+1, m_NormalRect.right - m_NormalRect.left-2, m_NormalRect.bottom - m_NormalRect.top-2,FALSE);
        SetPlayWindowRect(m_NormalRect,&bChangeSize);
        //::InvalidateRect(m_hOldWndParent,&m_NormalRect,TRUE);
        ::ShowWindow(m_hWndScreen,SW_HIDE);
    }
    RefreshSurface();

    return 0;
}

STDMETHODIMP CTopseePlayer::SetPlayWindowRect(RECT CtrlRect,  BOOL* retval)
{
    ShowWindow(SW_HIDE);
    BOOL bChangeSize = FALSE;
//     RECT clientRect;
//     GetClientRect(&clientRect);//GetWindowRect(&clientRect);//获取当前窗口的位置

    //bChangeSize = MoveWindow(CtrlRect.left+1, CtrlRect.top+1, CtrlRect.right - CtrlRect.left-2, CtrlRect.bottom - CtrlRect.top-2);

    RECT CtrlRectC;
    GetWindowRect(&CtrlRectC);//获取当前窗口的位置
    POINT pt1,pt2;
    pt1.x = CtrlRect.left;
    pt1.y = CtrlRect.top;
    ::ClientToScreen(GetParent(), &pt1);
    pt2.x = CtrlRect.right;
    pt2.y = CtrlRect.bottom;
    ::ClientToScreen(GetParent(), &pt2);

    bChangeSize = SetWindowPos( HWND_TOPMOST, pt1.x, pt1.y, (pt2.x - pt1.x), (pt2.y - pt1.y), SWP_FRAMECHANGED);
    ////SWP_SHOWWINDOW | SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER))
    ShowWindow(SW_SHOWMAXIMIZED);

    hash_map<int, Media*>::const_iterator iter;
    pLock->GetReadLock();
    if( (iter = media_map.begin()) != media_map.end())
    {
        Media* pMedia = iter->second;
        //CopyRect(&pMedia->rc, &CtrlRect);
        pMedia->left = 0;//Left;//
        pMedia->top = 0;//Top;//
        pMedia->right = 1;//Right;//
        pMedia->bottom = 1;//Bottom;//
    }
    pLock->ReleaseReadLock();

    * retval = bChangeSize;

    return S_OK;
}
STDMETHODIMP CTopseePlayer::RefreshSurface()
{
    RECT clientRect;
    GetClientRect(&clientRect);//GetWindowRect(&clientRect);//获取当前窗口的位置
    InvalidateRect(&clientRect);
    //     RECT RectParent;
    //     ::GetClientRect(m_hOldWndParent,&RectParent);
    return S_OK;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微澜-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值