恢复后工具栏是被选中的。但是没有显示。重新选它一次才出来。
解决方案 »
- 树节点复选框变灰
- 有没有可能 插入 system 进程,hook其中的注册表API函数?
- 生成的DLL在Debug版本中能够链接,而在Release版本中却不能够链接
- 请问金山影霸、超级解霸等媒体播放器的抓屏原理是怎么回事?
- 怎样将日期类型转换为字符串???
- 如何拖动无标题栏窗体谢谢!
- 急呀!快疯了!!!CDocManager那来的类呀!!!!!!
- 请问怎么在CListCtrl的item上右击鼠标时在鼠标的位置弹出快捷菜单?在线等。。。
- VC 的 ocx 是怎么使用系统的 dll 的
- 菜鸟的问题别笑!
- CSocket类问题,判断特定IP和断口的连接问题,高难度级。
- 高手都到那里去了,很菜的问题怎么没人回答
class CMainFrame : public CSDIFrameWnd
{
DECLARE_DYNAMIC(CMainFrame)
public:
CMainFrame(); // Attributes
public: // Operations
public: // Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMainFrame)
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL // Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif BOOL GetFullScreenSize(CWnd* pWnd, POINT& pt) const; protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar; CWnd* m_pWndFullScreen;
WINDOWPLACEMENT m_PreviousPlace;
WINDOWPLACEMENT m_MainPreviousPlace;
CRect m_FullScreenPlace;
CRect m_MainFullScreenPlace;
BOOL m_bHadToolBar;
BOOL m_bHadStatusBar; public:
void EscapeFullScreen(); // Generated message map functions
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnViewFullScreen();
afx_msg void OnUpdateViewFullScreen(CCmdUI* pCmdUI);
afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
}; void CMainFrame::EscapeFullScreen()
{
if (m_pWndFullScreen != NULL)
OnViewFullScreen();
}
void CMainFrame::OnViewFullScreen()
{
TRACE("m_wndStatusBar == %d\n", m_wndStatusBar.IsWindowVisible());
TRACE("m_wndToolBar == %d\n", m_wndToolBar.IsWindowVisible()); if (m_pWndFullScreen != NULL)
{
// If we are returning the app to the Maximized state, SetWindowPlacement()
// draws the entire app twice - once to its "Normal" state, then once to
// the maximized state. The LockWindowUpdate() calls suppress the extra
// redraw. ShowControlBar(&m_wndToolBar, m_bHadToolBar, FALSE);
ShowControlBar(&m_wndStatusBar, m_bHadStatusBar, FALSE); m_pWndFullScreen->LockWindowUpdate();
m_pWndFullScreen->SetWindowPlacement(&m_PreviousPlace);
m_pWndFullScreen->UnlockWindowUpdate(); LockWindowUpdate();
SetWindowPlacement(&m_MainPreviousPlace);
UnlockWindowUpdate();
m_pWndFullScreen = NULL;
}
else
{
m_pWndFullScreen = MDIGetActive();
ASSERT(m_pWndFullScreen != NULL); m_bHadToolBar = m_wndToolBar.IsWindowVisible();
m_bHadStatusBar = m_wndStatusBar.IsWindowVisible();
ShowControlBar(&m_wndToolBar, FALSE, FALSE);
ShowControlBar(&m_wndStatusBar,FALSE, FALSE); m_pWndFullScreen->GetWindowPlacement(&m_PreviousPlace);
GetWindowPlacement(&m_MainPreviousPlace); CRect rectDesktop;
if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, &rectDesktop, 0))
::GetWindowRect(::GetDesktopWindow(), &rectDesktop);
else
{
rectDesktop.right = ::GetSystemMetrics(SM_CXSCREEN);
rectDesktop.bottom = ::GetSystemMetrics(SM_CYSCREEN);
rectDesktop.right -= rectDesktop.left;
rectDesktop.bottom -= rectDesktop.top;
rectDesktop.left = -rectDesktop.left;
rectDesktop.top = -rectDesktop.top;
} TRACE("Going to (%d,%d) - (%d,%d)\n", rectDesktop.left, rectDesktop.top,
rectDesktop.right, rectDesktop.bottom); CRect rectDesired = rectDesktop;
::AdjustWindowRect(&rectDesktop, GetStyle(), TRUE); TRACE("Adjusted to (%d,%d) - (%d,%d)\n", rectDesktop.left, rectDesktop.top,
rectDesktop.right, rectDesktop.bottom); rectDesktop.bottom += ::GetSystemMetrics(SM_CYBORDER); // See "Ask Dr. GUI #10"
m_FullScreenPlace = rectDesktop;
m_MainFullScreenPlace = rectDesktop; WINDOWPLACEMENT wpNew = m_PreviousPlace;
wpNew.showCmd = SW_SHOWNORMAL;
wpNew.rcNormalPosition = rectDesktop; LockWindowUpdate();
SetWindowPlacement(&wpNew);
UnlockWindowUpdate(); TRACE("Before MDI Child to (%d,%d) - (%d,%d)\n", wpNew.rcNormalPosition.left, wpNew.rcNormalPosition.top,
wpNew.rcNormalPosition.right, wpNew.rcNormalPosition.bottom); wpNew.rcNormalPosition = rectDesired;
::AdjustWindowRect(&(wpNew.rcNormalPosition), m_pWndFullScreen->GetStyle(), FALSE); TRACE("MDI Child to (%d,%d) - (%d,%d)\n", wpNew.rcNormalPosition.left, wpNew.rcNormalPosition.top,
wpNew.rcNormalPosition.right, wpNew.rcNormalPosition.bottom); m_pWndFullScreen->LockWindowUpdate();
m_pWndFullScreen->SetWindowPlacement(&wpNew);
m_pWndFullScreen->UnlockWindowUpdate();
}
}
}
大家知道,在MFC框架中并没有提供现成的类或者函数来实现全屏显示特性,至少我到目前为止是没有发现。但是要实现这个特性也并不难。其基本思路是调整主窗口的大小和位置,使视图的显示充满屏幕。它需要以屏幕左上角为原点,处理x,y方向上的负坐标。本文拟用“使用GDI+进行图像处理”一文中的例子代码作为基础,实现视图的全屏显示。我在原来代码中增加了一个可重用的C++类CFullScreenHandler,顾名思义,这个类的作用就是专门用来实现全屏显示特性的,它封装了所有的实现细节,只要你把它加到自己的工程代码中,不用怎么修改就能是程序具备全屏显示功能。这个类中有两个重要的方法调用:第一、Maximize进入全屏显示模式,注意了,这里的全屏显示模式并不是平常我们说的窗口最大化按钮哦。第二、Restore方法用来恢复原来的窗口框架。CFullScreenHandler还提供了一个InFullScreenMode方法,用它来检查程序是否处于全屏显示状态,这些方法都通过一个CFullScreenHandler全程对象实例来调用。下面是程序的主窗口处理命令,全屏显示特性由“查看”菜单中的“全屏显示(&U)”触发执行,关键代码如下: void CMainFrame::OnViewFullScreen()
{
if (FullScreenHandler.InFullScreenMode())
FullScreenHandler.Restore(this);
else
FullScreenHandler.Maximize(this);
}
一旦进入全屏显示方式,那么标题栏、菜单栏和工具栏都会消失。千万别忘了告诉用户如何恢复原样,在OnDraw函数中加上几句即可: void CPictureView::OnDraw(CDC* pDC)
{
...... if (*ppic) {
......
pDC->DrawText(FullScreenHandler.InFullScreenMode() ?
_T("恢复窗口按 Ctrl-U 或者在客户区双击鼠标") : _T(""), &rc, 0);
}
}
如图一所示:
图一 给用户的恢复提示 之所以一定要给用户这种提示,是因为Windows程序的一个重要的GUI特点就是界面操作的自解释。否则,当用户进入全屏显示模式后(有意或无意),如果找不到恢复的方法便会令用户感到不知所措。
下面我们就来看看CFullScreenHandler::Maximize和Restore的工作原理:其实这些代码没有什么高深的东西,只是一些象素计算而已。Maximize首先在m_rcRestore数据成员中保存当前框架的位置,然后计算期望的屏幕尺寸。如图二所示:
图二 计算期望的屏幕尺寸 获得屏幕尺寸的方法是调用GetSystemMetrics函数。 Restore函数比Maximize更简单,它用m_rcRestore成员变量中保存的值将框架恢复到原来的样子,然后调用m_rcRestore.SetRectEmpty来表示框架不再处于全屏显示状态。就这么简单。
程序中有一个地方要说明一下,那就是OnGetMinMaxInfo函数的作用。你可以试一下,如果把这个函数去掉,则当你按下工具栏中的全屏显示按钮时,框架视图确实变大了,但没有想象的那样实现全屏显示,底边留下一个状态栏——一个有些发育不良的全屏显示窗口。为什么会这样呢?经过调试后,发现问题出在WM_GETMINMAXINFO消息的处理上。在Windows中,无论什么时候以何种方式改变窗口的尺寸或大小,是拖拽窗口边缘也好,或是在代码中调用改变窗口尺寸的函数也好,总之不管你用什么方法,Windows都会首先发送WM_GETMINMAXINFO消息。这个消息的意思是说:“嘿,如果你要强迫我的尺寸变大或变小,就附上详细的MINMAXINFO结构信息,否则我用默认值处理。”大多数应用程序都不用显式处理这个WM_GETMINMAXINFO消息(也就是说让DefWindowProc窗口过程进行缺省处理),而Windows在进行缺省处理时是不会让一个窗口视图比屏幕还大的,所以我们会碰上前面讲的那个问题。解决的方法是:不要让Windows对WM_GETMINMAXINFO消息进行缺省处理,而是由我们自己处理,方法如下: void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpmmi)
{
CSize sz = FullScreenHandler.GetMaxSize();
lpmmi->ptMaxSize = CPoint(sz);
lpmmi->ptMaxTrackSize = CPoint(sz);
}
这里CFullScreenHandler.GetMaxSize 返回的最大尺寸要比整个屏幕稍微大一点。 CSize CFullScreenHandler::GetMaxSize()
{
CRect rc(0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
rc.InflateRect(10,50);
return rc.Size();
}
GetMaxSize 返回的值分别是2×10=20和2×50=100象素,比屏幕自身的水平值和垂直值稍大。至于要大多少,我认为只要一个比屏幕大的模糊值即可。如果你硬要知道屏幕的精确尺寸,自己可以计算一下。