2121#include " Q1ViewVersion.h"
2222
2323#include < cmath>
24+ #include < dwmapi.h>
25+
26+ #pragma comment(lib, "dwmapi.lib")
2427
2528#ifdef _DEBUG
2629#define new DEBUG_NEW
@@ -38,6 +41,9 @@ const bool printPlaySpeed = false;
3841
3942#define WM_VIEWER_PLAY_TIMER (WM_APP + 1 )
4043
44+ static const UINT_PTR VIEWER_FULLSCREEN_DWM_TIMER = 0x5100 ;
45+ static const UINT VIEWER_FULLSCREEN_DWM_DELAY_MS = 250 ;
46+
4147enum QMouseMenuID
4248{
4349 QMouseMenuStart = 0x10000000 ,
@@ -72,6 +78,7 @@ BEGIN_MESSAGE_MAP(CViewerView, CView)
7278 ON_WM_DESTROY()
7379 ON_WM_CREATE()
7480 ON_WM_SIZE()
81+ ON_WM_TIMER()
7582 ON_WM_SETCURSOR()
7683 ON_WM_RBUTTONUP()
7784 ON_MESSAGE(WM_VIEWER_PLAY_TIMER , CViewerView::OnPlayTimer)
@@ -120,7 +127,7 @@ CViewerView::CViewerView()
120127, mFullMode(false )
121128, mShowCoord(false )
122129, mShowBoxInfo(true )
123- , mWasZoomed (false )
130+ , mHavePreFullPlacement (false )
124131, mHexMode(false )
125132, mShowSourceYuv(true )
126133, mRgbHex(_T(" %02X\n %02X\n %02X" ))
@@ -129,6 +136,9 @@ CViewerView::CViewerView()
129136, mNewSel(false )
130137, mDeltaIdx(-1 )
131138{
139+ ::ZeroMemory (&mPreFullPlacement , sizeof (mPreFullPlacement ));
140+ mPreFullPlacement .length = sizeof (mPreFullPlacement );
141+
132142 LOGFONT lf;
133143
134144 ::ZeroMemory (&lf, sizeof (lf));
@@ -262,11 +272,16 @@ void CViewerView::AdjustWindowSize()
262272
263273void CViewerView::FitToWindow ()
264274{
265- // The frame size is unchanged, so OnSize did not run; refresh the canvas
266- // extent from the current client size in case Initialize() toggled the
267- // per-frame progress bar for the newly loaded source.
275+ CRect rcClient;
276+ GetClientRect (&rcClient);
277+ mWClient = rcClient.Width ();
278+ mHClient = rcClient.Height ();
279+
280+ // Refresh the canvas extent from the actual client size. During frame style
281+ // changes OnSize can arrive after the first repaint, so do not rely on the
282+ // cached size when fitting a full-screen transition.
268283 mWCanvas = mWClient ;
269- mHCanvas = mHClient - mHProgress ;
284+ mHCanvas = max ( 0 , mHClient - mHProgress ) ;
270285
271286 // Scale the freshly loaded image so the whole image is visible in the
272287 // current viewport, without touching the frame size. Mirroring common
@@ -1696,32 +1711,69 @@ void CViewerView::ToggleFullScreen()
16961711{
16971712 // In this SDI app the view's parent is CMainFrame.
16981713 CMainFrame *pMainFrm = static_cast <CMainFrame *>(AfxGetMainWnd ());
1699- mFullMode = !mFullMode ;
1700-
1701- if (mFullMode ) {
1702- pMainFrm->SetMenu (NULL );
1703- if (pMainFrm->IsZoomed ()) {
1704- pMainFrm->SendMessage (WM_SYSCOMMAND , SC_RESTORE ,
1705- (LPARAM )pMainFrm->GetSafeHwnd ());
1706- mWasZoomed = true ;
1714+ if (pMainFrm == NULL )
1715+ return ;
1716+
1717+ const bool entering = !mFullMode ;
1718+ pMainFrm->SetRedraw (FALSE );
1719+ SetRedraw (FALSE );
1720+ ::LockWindowUpdate (pMainFrm->GetSafeHwnd ());
1721+ KillTimer (VIEWER_FULLSCREEN_DWM_TIMER );
1722+ BOOL disableDwmTransitions = TRUE ;
1723+ ::DwmSetWindowAttribute (pMainFrm->GetSafeHwnd (),
1724+ DWMWA_TRANSITIONS_FORCEDISABLED,
1725+ &disableDwmTransitions,
1726+ sizeof(disableDwmTransitions));
1727+
1728+ if (entering) {
1729+ mPreFullPlacement .length = sizeof (mPreFullPlacement );
1730+ mHavePreFullPlacement = pMainFrm->GetWindowPlacement (&mPreFullPlacement ) != FALSE ;
1731+ if (mPreFullPlacement .showCmd == SW_SHOWMINIMIZED )
1732+ mPreFullPlacement .showCmd = SW_SHOWNORMAL ;
1733+
1734+ mFullMode = true ;
1735+
1736+ MONITORINFO mi = {};
1737+ mi.cbSize = sizeof (mi);
1738+ HMONITOR hmon = ::MonitorFromWindow (pMainFrm->GetSafeHwnd (), MONITOR_DEFAULTTONEAREST );
1739+ if (::GetMonitorInfo (hmon, &mi)) {
1740+ CRect rc (mi.rcMonitor );
1741+ pMainFrm->SetMenu (NULL );
1742+ pMainFrm->ModifyStyle (
1743+ WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ,
1744+ WS_POPUP , 0 );
1745+ pMainFrm->SetWindowPos (&CWnd::wndTop, rc.left , rc.top ,
1746+ rc.Width (), rc.Height (),
1747+ SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_NOREDRAW );
17071748 }
1708- pMainFrm->ModifyStyle (WS_CAPTION | WS_SYSMENU , WS_POPUP , SWP_FRAMECHANGED );
1709- pMainFrm->SendMessage (WM_SYSCOMMAND , SC_MAXIMIZE ,
1710- (LPARAM )pMainFrm->GetSafeHwnd ());
17111749 } else {
1750+ mFullMode = false ;
17121751 HMENU hMenu = ::LoadMenu (theApp.m_hInstance , MAKEINTRESOURCE (IDR_MAINFRAME ));
17131752 ::SetMenu (pMainFrm->GetSafeHwnd (), hMenu);
1714- pMainFrm->ModifyStyle (WS_POPUP , WS_CAPTION | WS_SYSMENU , SWP_FRAMECHANGED );
1753+ pMainFrm->ModifyStyle (WS_POPUP ,
1754+ WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE |
1755+ WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU | WS_THICKFRAME ,
1756+ 0 );
17151757 pMainFrm->AddMainMenu ();
17161758 GetDocument ()->UpdateMenu();
1717- pMainFrm-> SendMessage ( WM_SYSCOMMAND , SC_RESTORE ,
1718- ( LPARAM ) pMainFrm->GetSafeHwnd() );
1719- if ( mWasZoomed ) {
1720- pMainFrm->SendMessage ( WM_SYSCOMMAND , SC_MAXIMIZE ,
1721- ( LPARAM ) pMainFrm->GetSafeHwnd ());
1722- mWasZoomed = false ;
1723- }
1759+ if ( mHavePreFullPlacement )
1760+ pMainFrm->SetWindowPlacement(& mPreFullPlacement );
1761+ else
1762+ pMainFrm->ShowWindow ( SW_RESTORE );
1763+ pMainFrm->SetWindowPos ( NULL , 0 , 0 , 0 , 0 ,
1764+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
1765+ SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_NOREDRAW );
17241766 }
1767+
1768+ pMainFrm->RecalcLayout (TRUE );
1769+ FitToWindow ();
1770+ pMainFrm->SetRedraw (TRUE );
1771+ SetRedraw (TRUE );
1772+ ::LockWindowUpdate (NULL );
1773+ pMainFrm->SetForegroundWindow ();
1774+ pMainFrm->RedrawWindow (NULL , NULL ,
1775+ RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE );
1776+ SetTimer (VIEWER_FULLSCREEN_DWM_TIMER , VIEWER_FULLSCREEN_DWM_DELAY_MS , NULL );
17251777}
17261778
17271779void CViewerView::ToggleHelp ()
@@ -2049,6 +2101,16 @@ void CViewerView::OnDestroy()
20492101{
20502102 CView::OnDestroy ();
20512103
2104+ KillTimer (VIEWER_FULLSCREEN_DWM_TIMER );
2105+ CMainFrame *pMainFrm = static_cast <CMainFrame *>(AfxGetMainWnd ());
2106+ if (pMainFrm != NULL ) {
2107+ BOOL disableDwmTransitions = FALSE ;
2108+ ::DwmSetWindowAttribute (pMainFrm->GetSafeHwnd (),
2109+ DWMWA_TRANSITIONS_FORCEDISABLED,
2110+ &disableDwmTransitions,
2111+ sizeof(disableDwmTransitions));
2112+ }
2113+
20522114 mBufferPool ->disable ();
20532115 mBufferQueue ->destroy ();
20542116 KillPlayTimer ();
@@ -2090,6 +2152,24 @@ void CViewerView::OnSize(UINT nType, int cx, int cy)
20902152 mRcProgress .SetRect (0 , mHCanvas , mWClient , mHClient );
20912153}
20922154
2155+ void CViewerView::OnTimer (UINT_PTR nIDEvent)
2156+ {
2157+ if (nIDEvent == VIEWER_FULLSCREEN_DWM_TIMER ) {
2158+ KillTimer (VIEWER_FULLSCREEN_DWM_TIMER );
2159+ CMainFrame *pMainFrm = static_cast <CMainFrame *>(AfxGetMainWnd ());
2160+ if (pMainFrm != NULL ) {
2161+ BOOL disableDwmTransitions = FALSE ;
2162+ ::DwmSetWindowAttribute (pMainFrm->GetSafeHwnd (),
2163+ DWMWA_TRANSITIONS_FORCEDISABLED,
2164+ &disableDwmTransitions,
2165+ sizeof(disableDwmTransitions));
2166+ }
2167+ return ;
2168+ }
2169+
2170+ CView::OnTimer (nIDEvent);
2171+ }
2172+
20932173void CViewerView::OnRButtonUp (UINT nFlags, CPoint point)
20942174{
20952175 if ((!mRcVolume .IsRectEmpty () && mRcVolume .PtInRect (point)) ||
0 commit comments