前言
一些资格较老的CE软件开发师应该还记得CE2.11版的系统界面吧。那时,系统界面比较忠实于PC版的WINDOWS系统界面,导航栏在最下方,“开始”菜单在导航栏的左侧,建立的单文档应用程序占据除导航栏外的整个屏幕,对话框程序带上标题栏后就可以随意拖动,一切都是那么的符合习惯,那么的舒服!
然而好景不常在,2001年,CE系统进行了一次革命性的升级,推出针对PDA的掌上系统PPC,版本提升到了3.0。这次的升级改变了整个系统界面,导航栏被安排在屏幕的最上方,但最下方还有一个用来放置输入键盘等工具的任务栏。这就使得本来就不大的程序显示界面变得更为紧张!但微软的工程师用了一些小技巧来解决单文档显示界面的紧张问题,方法就是把单文档中的菜单栏默认安置在任务栏。下面是两张效果图,大家可以对比一下:
CE2.11的单文档显示界面
CE3.0的单文档显示界面
单文档全屏
虽然这种方式的改变对对话框程序是一种“难言的痛”,但对于单文档程序,改变也不算大,只是一些使用习惯的问题而已。可是,谁都希望自己的程序能够在这个巴掌大的PDA上占据尽量大的显示空间,所以,我们可以做一些技术处理,隐藏掉导航栏,实现真正的全屏。
当菜单栏与最下面的任务栏合并在一起时,要实现单文档全屏,总的来说,只需要在几个位置加一些简单的代码。第一个位置是在CMainFrame::OnCreate函数(如果是SDK编程,相当于WM_CREATE的消息处理部分),在这里,需要添加一个移动窗口的动作,目的就是把程序的窗口移到屏幕的最顶端,代码如下:
RECT rc; //建立一个矩形变量
GetWindowRect(&rc ); //获取程序框架的窗口矩形位置
rc.top -= 26; //上移26个像素(导航栏的高度正好是26)
MoveWindow(rc.left, rc.top, rc.right, rc.bottom, TRUE ); //移动窗口
移动窗口后,还不能实现全屏,因为还有一个导航栏遮盖在程序的前面。所以我们要增加隐藏导航栏的代码,考虑到要在任何情况下都要隐藏导航栏,所以这些代码需要加在程序活动的时候。因此,我们在CMainFrame::DefWindowProc函数中增加对消息WM_ACTIVATE的处理,代码如下:
switch ( message )
{
case WM_ACTIVATE:
SHFullScreen( this->m_hWnd, SHFS_HIDETASKBAR);
break;
}
很明显,上面最为重要的代码行就是对SHFullScreen函数的调用,该函数属于Shell编程的一部分,第一个参数是程序框架句柄,第二个参数是状态申明,有以下申明(自己的一些翻译,也许会有一点小差异,^_^!):
SHFS_SHOWTASKBAR 使任务栏位于所有的窗口之上。
SHFS_HIDETASKBAR 隐藏任务栏,一个游戏或应用程序需要接管整个屏幕时应该使用该标志。但在使用该标志前应确保其有FULL SCREEN的大小,否则任务栏还是会出现。.
SHFS_SHOWSIPBUTTON 显示键盘
SHFS_HIDESIPBUTTON 隐藏键盘
SHFS_SHOWSTARTICON 显示导航栏上的“开始”。
SHFS_HIDESTARTICON 隐藏导航栏上的“开始”,当隐藏了“开始”,点击导航栏的时候将不会出现下拉“开始”菜单。
试运行一下,程序已可以全屏显示了,但刹那的光辉不代表灿烂的永恒,这么容易就可以解决的话,也就不叫问题了。
事实上,对于某些应用程序,输入键盘是一定要的,所以它不可能隐藏键盘,但操作过程中发现,如果弹出键盘后,导航栏将再次出现!前面所做的就犹如“竹篮打水一场空”!
因此,下面一步至关重要!
首先,在你的框架声明文件中(默认名字是MainFrm.h)加入一句申明:
afx_msg int OnSettingChange();
然后,在你的框架实现文件中(默认名字是MainFrm.cpp)加入消息映射:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_SETTINGCHANGE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
这里就是重点,是对系统参数改变消息的处理,如果你是SDK编程,就是对WM_SETTINGCHANGE消息的处理。好,下面我们为该消息添加处理代码:
int CMainFrame::OnSettingChange()
{
return 1;
}
有意思吧,代码处理就是什么都不做,直接就给它返回1。
再运行程序试试,弹出键盘,怎么样?全屏百分百!
还有很多情况处理,待续……
接续……
上面说的是菜单栏与最下面的任务栏合并在一起时的解决方法,对于菜单栏在程序顶端的情况,上面的处理方法还未能实现完全全屏的目标,因为还没有隐藏任务栏,图示如下:
没有隐藏任务栏
所以,我们还要对任务栏做隐藏处理。下面我就详细讲解实现的方法和步骤。
我们第一步要了解的是结构SHINITDLGINFO。这个结构的定义如下:
typedef struct tagSHINITDIALOG{
DWORD dwMask;
HWND hDlg;
DWORD dwFlags;
} SHINITDLGINFO;
dwMask:具体什么意思,我也不是很清楚,估计是掩码之类。事实上,现在只有一个取值,就是0x0001。可以用符号SHIDIM_FLAGS代表。
hDlg:英文翻译就是对话框的句柄,但是在单文档程序中取的是框架的句柄。
dwFlags:一个至关重要的标志参数。
SHIDIF_DONEBUTTON -- 在导航栏上显示能关闭程序的“OK”按钮;
SHIDIF_SIZEDLG --对话框的尺寸,不包括输入面板的位置;
SHIDIF_SIZEDLGFULLSCREEN ― 全屏尺寸,但忽略输入面板;
SHIDIF_SIPDOWN - 收起输入面板;
SHIDIF_FULLSCREENNOMENUBAR - 全屏尺寸,且占据最下部菜单栏的空间。
明白这个结构后就好办了,只需要加入以下代码就可以实现真正的全屏:
SHINITDLGINFO shidi;
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_SIPDOWN | SHIDIF_FULLSCREENNOMENUBAR;
shidi.hDlg = this->m_hWnd;
SHInitDialog( &shidi );
注意了,以上代码要加在MoveWindow语句之前。
顺便提醒一下,如果你还想隐藏输入面板的话,就把
SHFullScreen( this->m_hWnd, SHFS_HIDETASKBAR);
改为:
SHFullScreen( this->m_hWnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON );
最后实现的单文档全屏图示如下:
下次讲解对话框全屏的原理。待续……
对话框假全屏的关闭和真正全屏的实施
对话框在PPC2000以上也是默认全屏的,无论你的对话框有多小,它就是自动全屏,但遗憾的是,这个全屏不是真正的全屏,因为它始终需要搭配个导航栏和任务栏,把界面搞得非常难看。幸运的是,这只是个默认值,不是固定值。我们可以通过实施某些手段来改变这种状态。
最简单的方法就是使用对话框新增的一个内部属性m_bFullScreen。这是个布尔变量,当它为TRUE时,对话框全屏;为FALSE时,对话框为实际大小。那么,如何使用该变量呢?这也很简单,只需要在初始对话框前,给这个属性赋值就行了,如下:
BOOL CXXXDlg::OnInitDialog()
{
m_bFullScreen = FALSE;
CDialog::OnInitDialog();
return TRUE;
}
如果是SDK编程,你就在初始化消息下处理就行了。
当然,如果这么简单就完了,也就不需要写这种费力不讨好的文章了,屏蔽这个全屏后,你会发现一旦使用键盘,对话框就会回复原型。这是不可接受的,所以,我们还要做一些消息处理,这个消息就是WM_SETTINGCHANGE,处理的地方和方法请参考上面单文档的描述。
上面说了如何屏蔽假全屏,接着就是对话框全屏的实施了,可是,我不打算在这里又罗里罗嗦地把单文档全屏所说的话重复一遍。所以,你如果需要实施对话框的真正全屏,完全可以参照单文档的做法,这里我就偷懒略去了。
[habit]在对话框下用上述方法不能把屏幕下方那个供输入的那行关闭,不能实现真正的全屏。把下边这句加入OnInitDialog()即可:
m_pWndEmptyCB->ShowWindow(SW_HIDE);
一些资格较老的CE软件开发师应该还记得CE2.11版的系统界面吧。那时,系统界面比较忠实于PC版的WINDOWS系统界面,导航栏在最下方,“开始”菜单在导航栏的左侧,建立的单文档应用程序占据除导航栏外的整个屏幕,对话框程序带上标题栏后就可以随意拖动,一切都是那么的符合习惯,那么的舒服!
然而好景不常在,2001年,CE系统进行了一次革命性的升级,推出针对PDA的掌上系统PPC,版本提升到了3.0。这次的升级改变了整个系统界面,导航栏被安排在屏幕的最上方,但最下方还有一个用来放置输入键盘等工具的任务栏。这就使得本来就不大的程序显示界面变得更为紧张!但微软的工程师用了一些小技巧来解决单文档显示界面的紧张问题,方法就是把单文档中的菜单栏默认安置在任务栏。下面是两张效果图,大家可以对比一下:
CE2.11的单文档显示界面
CE3.0的单文档显示界面
单文档全屏
虽然这种方式的改变对对话框程序是一种“难言的痛”,但对于单文档程序,改变也不算大,只是一些使用习惯的问题而已。可是,谁都希望自己的程序能够在这个巴掌大的PDA上占据尽量大的显示空间,所以,我们可以做一些技术处理,隐藏掉导航栏,实现真正的全屏。
当菜单栏与最下面的任务栏合并在一起时,要实现单文档全屏,总的来说,只需要在几个位置加一些简单的代码。第一个位置是在CMainFrame::OnCreate函数(如果是SDK编程,相当于WM_CREATE的消息处理部分),在这里,需要添加一个移动窗口的动作,目的就是把程序的窗口移到屏幕的最顶端,代码如下:
RECT rc; //建立一个矩形变量
GetWindowRect(&rc ); //获取程序框架的窗口矩形位置
rc.top -= 26; //上移26个像素(导航栏的高度正好是26)
MoveWindow(rc.left, rc.top, rc.right, rc.bottom, TRUE ); //移动窗口
移动窗口后,还不能实现全屏,因为还有一个导航栏遮盖在程序的前面。所以我们要增加隐藏导航栏的代码,考虑到要在任何情况下都要隐藏导航栏,所以这些代码需要加在程序活动的时候。因此,我们在CMainFrame::DefWindowProc函数中增加对消息WM_ACTIVATE的处理,代码如下:
switch ( message )
{
case WM_ACTIVATE:
SHFullScreen( this->m_hWnd, SHFS_HIDETASKBAR);
break;
}
很明显,上面最为重要的代码行就是对SHFullScreen函数的调用,该函数属于Shell编程的一部分,第一个参数是程序框架句柄,第二个参数是状态申明,有以下申明(自己的一些翻译,也许会有一点小差异,^_^!):
SHFS_SHOWTASKBAR 使任务栏位于所有的窗口之上。
SHFS_HIDETASKBAR 隐藏任务栏,一个游戏或应用程序需要接管整个屏幕时应该使用该标志。但在使用该标志前应确保其有FULL SCREEN的大小,否则任务栏还是会出现。.
SHFS_SHOWSIPBUTTON 显示键盘
SHFS_HIDESIPBUTTON 隐藏键盘
SHFS_SHOWSTARTICON 显示导航栏上的“开始”。
SHFS_HIDESTARTICON 隐藏导航栏上的“开始”,当隐藏了“开始”,点击导航栏的时候将不会出现下拉“开始”菜单。
试运行一下,程序已可以全屏显示了,但刹那的光辉不代表灿烂的永恒,这么容易就可以解决的话,也就不叫问题了。
事实上,对于某些应用程序,输入键盘是一定要的,所以它不可能隐藏键盘,但操作过程中发现,如果弹出键盘后,导航栏将再次出现!前面所做的就犹如“竹篮打水一场空”!
因此,下面一步至关重要!
首先,在你的框架声明文件中(默认名字是MainFrm.h)加入一句申明:
afx_msg int OnSettingChange();
然后,在你的框架实现文件中(默认名字是MainFrm.cpp)加入消息映射:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_SETTINGCHANGE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
这里就是重点,是对系统参数改变消息的处理,如果你是SDK编程,就是对WM_SETTINGCHANGE消息的处理。好,下面我们为该消息添加处理代码:
int CMainFrame::OnSettingChange()
{
return 1;
}
有意思吧,代码处理就是什么都不做,直接就给它返回1。
再运行程序试试,弹出键盘,怎么样?全屏百分百!
还有很多情况处理,待续……
接续……
上面说的是菜单栏与最下面的任务栏合并在一起时的解决方法,对于菜单栏在程序顶端的情况,上面的处理方法还未能实现完全全屏的目标,因为还没有隐藏任务栏,图示如下:
没有隐藏任务栏
所以,我们还要对任务栏做隐藏处理。下面我就详细讲解实现的方法和步骤。
我们第一步要了解的是结构SHINITDLGINFO。这个结构的定义如下:
typedef struct tagSHINITDIALOG{
DWORD dwMask;
HWND hDlg;
DWORD dwFlags;
} SHINITDLGINFO;
dwMask:具体什么意思,我也不是很清楚,估计是掩码之类。事实上,现在只有一个取值,就是0x0001。可以用符号SHIDIM_FLAGS代表。
hDlg:英文翻译就是对话框的句柄,但是在单文档程序中取的是框架的句柄。
dwFlags:一个至关重要的标志参数。
SHIDIF_DONEBUTTON -- 在导航栏上显示能关闭程序的“OK”按钮;
SHIDIF_SIZEDLG --对话框的尺寸,不包括输入面板的位置;
SHIDIF_SIZEDLGFULLSCREEN ― 全屏尺寸,但忽略输入面板;
SHIDIF_SIPDOWN - 收起输入面板;
SHIDIF_FULLSCREENNOMENUBAR - 全屏尺寸,且占据最下部菜单栏的空间。
明白这个结构后就好办了,只需要加入以下代码就可以实现真正的全屏:
SHINITDLGINFO shidi;
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_SIPDOWN | SHIDIF_FULLSCREENNOMENUBAR;
shidi.hDlg = this->m_hWnd;
SHInitDialog( &shidi );
注意了,以上代码要加在MoveWindow语句之前。
顺便提醒一下,如果你还想隐藏输入面板的话,就把
SHFullScreen( this->m_hWnd, SHFS_HIDETASKBAR);
改为:
SHFullScreen( this->m_hWnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON );
最后实现的单文档全屏图示如下:
下次讲解对话框全屏的原理。待续……
对话框假全屏的关闭和真正全屏的实施
对话框在PPC2000以上也是默认全屏的,无论你的对话框有多小,它就是自动全屏,但遗憾的是,这个全屏不是真正的全屏,因为它始终需要搭配个导航栏和任务栏,把界面搞得非常难看。幸运的是,这只是个默认值,不是固定值。我们可以通过实施某些手段来改变这种状态。
最简单的方法就是使用对话框新增的一个内部属性m_bFullScreen。这是个布尔变量,当它为TRUE时,对话框全屏;为FALSE时,对话框为实际大小。那么,如何使用该变量呢?这也很简单,只需要在初始对话框前,给这个属性赋值就行了,如下:
BOOL CXXXDlg::OnInitDialog()
{
m_bFullScreen = FALSE;
CDialog::OnInitDialog();
return TRUE;
}
如果是SDK编程,你就在初始化消息下处理就行了。
当然,如果这么简单就完了,也就不需要写这种费力不讨好的文章了,屏蔽这个全屏后,你会发现一旦使用键盘,对话框就会回复原型。这是不可接受的,所以,我们还要做一些消息处理,这个消息就是WM_SETTINGCHANGE,处理的地方和方法请参考上面单文档的描述。
上面说了如何屏蔽假全屏,接着就是对话框全屏的实施了,可是,我不打算在这里又罗里罗嗦地把单文档全屏所说的话重复一遍。所以,你如果需要实施对话框的真正全屏,完全可以参照单文档的做法,这里我就偷懒略去了。
[habit]在对话框下用上述方法不能把屏幕下方那个供输入的那行关闭,不能实现真正的全屏。把下边这句加入OnInitDialog()即可:
m_pWndEmptyCB->ShowWindow(SW_HIDE);