Windows CE开发常见问题解答
比如一个EditBox获得焦点后,这个时候自动打开软键盘,这样可以方便用户输入——SIPINFO、SHSIPINFO、SIPSETINFO、SIPGETINFO里面有些参数 弄不明白
//隐藏输入面板
BOOL LowerSip()
{
BOOL fRes = FALSE;
SIPINFO si;
memset( &si, 0, sizeof( si ) );
si.cbSize = sizeof( si );
if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) )
{
si.fdwFlags &= ~SIPF_ON;
fRes = SHSipInfo( SPI_SETSIPINFO, 0, &si, 0 );
}
return fRes;
}
//升起输入面板
BOOL RaiseSip( void )
{
BOOL fRes = FALSE;
SIPINFO si;
memset( &si, 0, sizeof( si ) );
si.cbSize = sizeof( si );
if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) )
{
si.fdwFlags |= SIPF_ON;
fRes = SHSipInfo( SPI_SETSIPINFO, 0, &si, 0 );
}
return fRes;
}
再试试下面这些:
//SHSipPreference(m_hWnd, SIP_UP);//弹出输入面板
//SHSipPreference(m_hWnd, SIP_DOWN);//隐藏输入面板(有一个时延)
//SHSipPreference(m_hWnd, SIP_FORCEDOWN );//隐藏输入面板(立即)
//SHSipPreference(m_hWnd, SIP_UNCHANGED );
//一般只用在调用SIP_DOWN时的的后面,使这个命令无效
--------------------------------------------------------------------------------
2.WinCE下字符串-数字转化的问题!
在VC6.0下,把#i nclude <stdlib.h>、#i nclude <stdio.h>两个文件包括进去后,下面这段代码一点问题没有,
CString str1,str2;
str1="123";
str2="123.4";
int i;
float j;
i=atoi(str1);
j=atof(str2);
但是在EVC3.0里面,却出现了问题:提示atof没有定义,atoi也不能正常转化。
用wcstoi,wcstof, wcstol和wcstod
--------------------------------------------------------------------------------
3. 我新拿了一个Pocket Pc,编了几个程序,但发现对话框都只能全屏显示,这是为什么?
一般在Pocket PC中所有的对话框都是全屏显示,这是操作系统规定的行为。但如使用系统自定义的信息提示框,则不是全屏显示。如: Afxmessagebox所激发的提示框就是如此。
可以重载WM_INITDIALOG消息
MSDN:
The DialogBox macro uses the CreateWindowEx function to create the dialog box. DialogBox then sends a WM_INITDIALOG message to the dialog box procedure. The function displays the dialog box (regardless of whether the template specifies the WS_VISIBLE style), disables the owner window, and starts its own message loop to retrieve and dispatch messages for the dialog box.
就是说当对话框窗口创建完以后,会发出一个WM_INITDIALOG 消息,你只要在自己的窗口消息处理函数里对这个消息进行处理,就可以了
比如:
case WM_INITDIALOG:
// Create a Done button and size it.
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
InitOptionDlg(hDlg);
return TRUE;
主要就是修改shidi.dwFlags ,看看ABOUT的窗口消息处理吧
补充: SHINITDLGINFO shidi;
SHINITDLGINFO shidi;
上面说的是在纯API的程序中的方法
对于MFC创建的DIALOG程序,可以这样:
BOOL CXXXDlg::OnInitDialog()
{
SHINITDLGINFO shidi;
HWND hDlg = m_hWnd;
// Create a Done button and size it.
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_SIPDOWN ;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
//InitOptionDlg(hDlg);
//CDialog::OnInitDialog();
……
}
--------------------------------------------------------------------------------
4.在eVC基于MFC的程序中如何将ToolBar栏隐藏
关于ToolBar的隐藏:
首先,如果你是用MFC向导创建的工程,则默认会生成ToolBar,我要说的是,干掉它!自己来创建。:)
First,声明CToolBar成员变量:
CToolBar * d_pToolbar2;
然后……
static UINT BASED_CODE Toolbar2Buttons[] =
{
// 下面是工具栏对应菜单的ID,工具栏图标是我弄的一个Bitmap,其ID为IDR_ADD_TOOLBAR
ID_FILE_NEW,
ID_FILE_OPEN,
ID_FILE_SAVE,
ID_SEPARATOR,
ID_EDIT_CUT,
ID_EDIT_COPY,
ID_EDIT_PASTE,
ID_SEPARATOR,
ID_TRANS_DICT,
ID_TOOLBAR_SHOW, //这是新加入的菜单项,点击隐藏工具栏,再点击就显示工具栏
};
然后……
在CMainFrame的OnCreate()中加入:
OnToolbarCreate();
然后……
void CMainFrame::OnToolbarCreate()
{
// Should only get here if we don't have a toolbar.
ASSERT(d_pToolbar2 == 0);
// Create C++ object and WinAPI window.
d_pToolbar2 = new CToolBar();
d_pToolbar2->Create(this, WS_CHILD | CBRS_BOTTOM |
CBRS_SIZE_FIXED | CBRS_FLOATING,
0x9100);
// Get bitmap and connect to tool items.
d_pToolbar2->LoadBitmap(IDR_ADD_TOOLBAR);
d_pToolbar2->SetButtons(Toolbar2Buttons,
sizeof(Toolbar2Buttons)/sizeof(UINT));
// Make toolbar dockable.
d_pToolbar2->EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(d_pToolbar2);
}
然后……
void CMainFrame::OnToolbarShow()
{
ASSERT(d_pToolbar2 != 0);
// Query current visibility.
BOOL bVisible = (d_pToolbar2->GetStyle() & WS_VISIBLE);
// Show or hide.
int nShow = (bVisible) ? SW_HIDE : SW_SHOWNORMAL;
d_pToolbar2->ShowWindow(nShow);
// Reconfigure remaining toolbar items.
RecalcLayout();
// Store visibility state for later.
d_bToolbarVisible = (!bVisible);
}
void CMainFrame::OnUpdateToolbarShow(CCmdUI* pCmdUI)
{
//This function is signed for checking the menu 'Edit|Show Toolbar'
pCmdUI->Enable(d_pToolbar2 != 0);
int nCheck = (d_bToolbarVisible) ? 1 : 0;
pCmdUI->SetCheck(nCheck);
}
OK,默认情况下ToolBar是隐藏的,点击菜单中的新加入的隐藏/显示工具栏命令即可来回切换了。
--------------------------------------------------------------------------------
5.如何制作pocket Pc 下的安装程序?
在C:/Windows CE Tools/wce300/MS Pocket PC/support/ActiveSync/windows ce application installation 下面有例子.
也有其它第三方的安装工具,比如installshield。
--------------------------------------------------------------------------------
6.怎样在主界面中显示一幅图片
我做了一个小程序, 想在主界面中显示一幅图片,我的图片是.JPG格式的,如果需要转换,用什么工具?
把JPG图转为BMP图咯,网上有不少这样的程序。
然后用LoadBitmap、SelectObject、StretchBlt等语句把BMP图显示到VIEW中。
--------------------------------------------------------------------------------
7. 请问,在WinCE下如何截获所有鼠标和键盘的消息?
wince下只能用三种钩子
#define WH_JOURNALRECORD 0
#define WH_JOURNALPLAYBACK 1
#define WH_KEYBOARD_LL 20
--------------------------------------------------------------------------------
8.在Pocket PC下用eVC作的对话框能否做成不是全屏的?
在MFC中
m_bFullScreen = FALSE;
--------------------------------------------------------------------------------
9.如何将char 类型的中文字符串转换成Unicode的字符串?
MultiByteToWideChar,在仿真器中无效;你也可以通过其他方法;用wcsprintf这个函数
--------------------------------------------------------------------------------
10. evc单文档界面中,菜单左边总有一个"new",如何将其去掉?
在MainFrm的OnCreate内找到这个:
m_wndCommandBar.m_bShowSharedNewButton = TRUE;
把TRUE改为FALSE
--------------------------------------------------------------------------------
11.Edit出现上下文菜单问题?
近 来我看了一下SDK带的Sample中的Npp,其中它有一个功能就是在EDIT上出现上下文菜单,可是当我仿照它在自己的项目中添加此功能时,即在资源 中添加CONTROL "",IDC_STATIC,"SIPPREF",NOT WS_VISIBLE,-10,-10、,6,6,在模拟器中正常,但在PDA中不能显示包含Edit的对话框。而Npp可以在两者正常显示。我又在 Npp中增加一个对话框,也相应的改变资源,结果是在模拟器和PDA中都能正常显示。
调用SHInitExtraControls()应该在构造函数,不应在OnInitDialog中。如果在OnInitDialog中调用,包含EDIT的对话框将不显示。
事实上在XXXApp::InitInstance函数中调用更好,这样只需调用一次,就万事大吉。
--------------------------------------------------------------------------------
12. 如何将.mdb数据库转换为.cdb数据库
如何将.mdb数据库转换为.cdb数据库,在没有实际PDA,只有Pocket PC Emuliation和EVB的情况下。
Pocket PC Emuliation运行时为何提示“存储器不足,无法完成操作”?
此问题微软已经给出了答案。
在SDK文档中有一个叫做device的例子程序,它就是将tdb文件转化成cdb文件的,而还有一个desktop的程序,它是将mdb文件转化成tdb文件的。
--------------------------------------------------------------------------------
13.请问如何用EVC建立和调用DLL
我按照帮助中用MFC开发DLL的例子做,但是另外一个程序调用的时候的时候却出现连接错误,说找不到那个函数。后来看了EVC的例子spintest之后也是这样。
和在WINDOWS下的一样
是不是LINK2001 ERROR?
你如果是隐式调用(就是不用LOADLIBRARY()的),要把你的DLL的LIB文件在PROJECT-->SETTINGS--->LINK--->INPUT里指明。
--------------------------------------------------------------------------------
14.编辑框如何自动会换行 ?
请教,Plam中的table控件,在Wince上怎么做?
就是编辑框自动会换行.当你输入的内容超过一行,自动切换到下一行,下面的内容自动往下滚。
勾选编辑控件的MultiLine,如果想输入回车换行,再勾选want renturn
--------------------------------------------------------------------------------
15.是否在adoce,pocket access中的update语句不能执行?
ADOCE不能直接执行UPDATE语句,但ADOCE有Update方法,你可用它实现。
--------------------------------------------------------------------------------
16.请问如何在Windows CE中实现BC++中的inport(...)与outportb(...)函数功能?
CE下,可以用WINDOWS API函数来对端口操作。 比较简单。
API一般只要用到CreateFile(打开端口,串口操作和文件操作只有一点不同就是打开方式不同,所以第三个参数 要用 OPEN_EXISTING )
COMMTIMEOUTS、DCB两个结构是存放设置参数 的,可以改
WriteFile、WriteFile(读写端口)
因为串口通讯用的是异步通讯,所以下面两句比较重要
SetCommMask(指定监视的端口事件)
WaitCommEvent(等待端口事件)
--------------------------------------------------------------------------------
17. 如何显示一个对话框让用户选择一个目录而不是文件
没有标准的函数处理这个,你只好自己实现活使用第三方的解决方案。
--------------------------------------------------------------------------------
18.有没有办法(API)激活或禁止电源保存模式?
参看SystemIdleTimerReset()的安装文档。创建一个包含象睡眠的无限循环的线程,然后调用SystemIdleTimerReset()。也许有一种中断线程的办法就是程序退出。
--------------------------------------------------------------------------------
19. Windows CE的文件名最小程度是多少?
在windef.h定义了MAX_PATH,普遍应该是260个字符。
20. 我使用CFileDialog创建了一个浏览按钮,默认目录始终是显示"All Folders"和在"/My Device/My do***ents"下。怎样改变初始目录到"/My Device"。使用fileDlg.m_ofn.lpstrInitialDir = TEXT(" [url=file://My/] file://My/ [/url] Device");,但是没有改变默认显示的目录。
lpstrInitialDir指向一个指定初始文件目录的字符串。如果为NULL,将使用系统的根目录。尽量尝试一下lpstrInitialDir为NULL。
--------------------------------------------------------------------------------
21.在Pocket PC任务栏上可能有X和OK按钮吗?
不可能,至少没有象WisBar的第三方工具。
--------------------------------------------------------------------------------
22.如何禁止用户改变日期和时间?有可能实现吗?
你可能用自己的程序替代/windows/clock.exe,但是,它们可以通过另外的程序处理这个。同样,在同步时ActiveSync改变设备的时间与PC匹配。
--------------------------------------------------------------------------------
23. 我有一个xscal cpu的ipaq 3970设备,但是在eMbedded Visual C++ 3.0上没有目标类型。我应该在EVC3.0上使用什么类型。这个问题也发生在安装程序Cabwiz.exe上。
你可以使用ARM类型。XScal基于ARM体系。
--------------------------------------------------------------------------------
24. 如何使程序在后台运行?
最小化程序将使程序进入后台,因此只要在程序启动时最小化,那么它将运行在后台。
补充:还可以做成service。
--------------------------------------------------------------------------------
25. 我准备去掉SIP按钮。我在OnInitDialog事件中使用SHFullScreen 。然而SIP按钮仍然可见,忘记做什么了吗?
代码如下:
// SHFullScreen fails if dialog box is not foreground.
SetForegroundWindow();
// Go to the full screen mode
SHFullScreen (m_hWnd, SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON);
不能在OnInitDialog中使用SHFullScreen ,因为对话框还没有可见。你应该传递一个自定义消息,在那个消息调用这个函数。
也许下面这段代码会有用:
void PFCSipButtonShow( BOOL bShow )
{
HWND hWnd = ::FindWindow( _T( "MS_SIPBUTTON" ), NULL );
if (hWnd == NULL)
return;
if (bShow)
::ShowWindow( hWnd, SW_SHOW );
else
::ShowWindow( hWnd, SW_HIDE );
} // PFCSipButtonShow
--------------------------------------------------------------------------------
26. 如何在Pocket PC2002模拟器上安装Pocket PC程序?
PPC2002 模拟器没有模拟ARM处理器,因此你必须有x86 CPU的二进制文件和相应的安装程序。只需使用文件浏览器复制cab文件到模拟器,然后执行它。商业程序的安装包通常不包含x86的二进制程序。如果你没 有x86处理器的程序发布版本,你不能做这个安装。如果程序是你自己的,你可以创建一个x86的版本,之后创建一个安装CAB。
--------------------------------------------------------------------------------
27. 如何在eVC程序中读取普通的图标文件?
在PC程序中使用ExtractIconEx(),但是在Pocket 设备好象不工作。缺少了什么?PC图标文件在Pocket PC环境是非法的?或者需要转换格式?
不幸的是,在Pocket PC上没有API去读取图标。因此,你不得不手工解析图标文件。
--------------------------------------------------------------------------------
28. 如何绘制一个透明的圆呢?
我想使用eVC++和GDI在Pocket PC 2002上绘制一个圆。我使用它绘制了直线,它处理的很好:
hbrOld =(HBRUSH) SelectObject(hDC, CreatePatternBrush(RGB(0,255,0)));
hpnOld =(HPEN) SelectObject(hDC, CreatePen(PS_SOLID, 2, RGB(255,0,0)));
Ellipse( hDC, 10, 10, 20, 20);
DeleteObject( SelectObject (hDC, hbrOld) );
DeleteObject( SelectObject (hDC, hpnOld) );
但是如何绘制一个透明的圆呢?有PS_NULL这样画笔类型吗?
可以使用GetStockObject()得到一个NULL_BRUSH或HOLLOW_BRUSH(这两个是相同的)。然后用SelectObject选择它,就象你已经做的那样。
--------------------------------------------------------------------------------
29. 假定我知道程序的名称,关闭运行着的eVC的程序使用什么API?
如果你知道程序的名称,并且假定与主窗口的名称相同,那么你可以使用FindWindow得到那个窗口的句柄,然后传送WM_CLOSE消息到那个窗口。
HWND hwnd = FindWindow(NULL, _T("APPLICATION NAME"));
if ( hwnd)
PostMessage(hwnd, WM_DESTROY, 0, 0);
--------------------------------------------------------------------------------
30. 如何从PC设置PDA的时间?
最简单的办法是写一个自定义的RAPI函数,通过CeRapi调用设备的SetSystemTime.
--------------------------------------------------------------------------------
31. 怎样使用WriteBinary,我不明白第二个参数 (LPBYTE):
BOOL CVORegistry::WriteBinary(LPCTSTR pcszKey, LPBYTE pData, DWORD cbData)
第二个参数 是指向包含你想写到注册表的二进制数据的缓冲。
BYTE data[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef };
extern CVORegistry reg;
reg.WriteData(_T("BinaryData"), data, sizeof(data));
--------------------------------------------------------------------------------
32. Windows CE支持钩子API吗?这样我们可以监视需要的时间。如果支持,用法也象Windows 2000那样吗?
坏消息:CE不支持钩子。
系统不支持,我们还是可以想其他办法的……
![](https://i-blog.csdnimg.cn/blog_migrate/2471b21bbfe68f84803d028cb5783dc6.png)
--------------------------------------------------------------------------------
33. 我不能使用Pocket PC上CDialog的TitleBar,我能用静态文本框控件替代,使之与TitleBar相似。有办法显示TitleBar吗?
大多数Pocket PC上的对话框是全屏的,没有自己的主题栏,而是使用系统任务栏。你可以创建一个非全屏对话框(象消息框那样)。
--------------------------------------------------------------------------------
34. 如何在程序中关闭(suspend)Pocekt PC?
方法1:虚拟关机键
::keybd_event(VK_OFF, 0, 0, 0);
::keybd_event(VK_OFF, 0, KEYEVENTF_KEYUP, 0);
方法2:调用未公开函数PowerOffSystem()
extern "C" __declspec(dllimport) void PowerOffSystem();
--------------------------------------------------------------------------------
35. 如何在程序中重启(soft reset)Pocket PC?
#i nclude
#define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
extern "C" __declspec(dllimport) BOOL KernelIoControl(
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned);
BOOL ResetPocketPC()
{
return KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);
}
--------------------------------------------------------------------------------
36. 如何在程序中硬启动(hardware reset)Pocekt PC?
注意:使用此段代码会将您的Pocket PC的用户数据全部清空。
#i nclude
#define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
extern "C" __declspec(dllimport)void SetCleanRebootFlag(void);
extern "C" __declspec(dllimport) BOOL KernelIoControl(
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned);
BOOL HardResetPocketPC()
{
SetCleanRebootFlag();
return KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);
}
--------------------------------------------------------------------------------
37. 以下方法信息不全,无法使用:
1.系统不认识VK_OFF
2.使用哪个dll 和 lib文件?
· 如何在程序中关闭(suspend)Pocekt PC?
方法1:虚拟关机键
::keybd_event(VK_OFF, 0, 0, 0);
::keybd_event(VK_OFF, 0, KEYEVENTF_KEYUP, 0);
方法2:调用未公开函数PowerOffSystem()
extern /"C/" __declspec(dllimport) void PowerOffSystem();
关闭(suspend)
方法1:
//虚拟关机键
::keybd_event(VK_OFF, 0, 0, 0);
::keybd_event(VK_OFF, 0, KEYEVENTF_KEYUP, 0);
方法2:
//调用未公开函数PowerOffSystem()
extern "C" __declspec(dllimport) void PowerOffSystem();
印象中,我的前任在开发WINCE应用时为了隐藏系统任务栏,达到全屏显示的效果,还稍微花了点周折。要求系统定制时要加入AYGShell组件,然后自己调用SHFullScreen ,然后再用了些连招,比如改改注册表、改改编译参数 来实现的。我试了一下SHFullScreen ,貌似效果出不来,不晓得哪里弄错了。
不管了,慢慢去查API的使用太温柔了,我们用暴力手段解决这个问题。
首先把模拟器跑起来,然后用eVC的Tools -> Remote Spy++连上去,看看任务栏窗口是在谁的地盘上。看到截图如下
看到它了,就是那个叫做“HHTaskBar”的煞笔。干掉它
HWND hwndTaskBar = FindWindow(TEXT("HHTaskBar"), NULL);
if(hwndTaskBar)
{
EnableWindow(hwndTaskBar, FALSE);
ShowWindow(hwndTaskBar, SW_HIDE);
}
失望啊,真没技术含量,才一刀就给剁了。不过咱们讲究的是效果,能一刀砍死就不需要动用华丽的大招了。
经过细致研究和严格测试 负责任的给出《史上最全面的Windows Mobile窗口全屏总结》
开发和测试环境: VC2005 智能MFC
测试样机:dopod E616
-------------------------------------------------------------------
第一点:全屏到底用什么API最好
在MSDN、网络资料等有一下几种全屏方法:(都是简记 )
1、SHFullScreen
2、ShowWindow(FindWindow) 利用循环找出所有menuworker等等的窗口
3、EnumWindows(EnumWindowsProc) => EnumWindowsProc{GetClassName;ShowWindow;}
事实上,第2和第3 是一回事,都是通过找窗口 把符合条件的窗口找到然后隐藏,就像我在第5楼 说的一样:使用FindWindow是个危险的做法 原因就在于,当用户主动结束掉应用程序,因来不及调用相应的显示而造成屏幕的部分系统级别的窗口缺失,让用户以为出了严重问题,我测试过,当用“运行的程序”结束进程,就会导致这类情况,当然重启WM可以恢复。(第4楼、第6楼就分别采用的这类方法)
然而,SHFullScreen是一个非常好的函数,他的参数是本窗体句柄,也就是说,无论在全屏后遭受如何的打击,即使进程强制关闭,都不会影响到系统 整体。我强烈推荐使用SHFullScreen。 甚至如果你太懒,你可以不负责任的不去编写逆全屏代码。当然我还是会编写,因为可能考虑到在程序运行期间的主动退出全屏模式的可能。
第二点 如何隐藏菜单
让我把SHFullScreen的原型写出来:
SHFullScreen
This function can be used to take over certain areas of the screen. It is used to modify the taskbar, Input Panel button, or Start menu icon.
它的相应的宏标志:SHFS_SHOWTASKBAR、SHFS_HIDETASKBAR、SHFS_SHOWSIPBUTTON、 SHFS_HIDESIPBUTTON、SHFS_SHOWSTARTICON、SHFS_HIDESTARTICON也只有 “任务栏”、“SIPB(Standard Input Panel Button)”、开始菜单按钮的有效性(即在全屏后,是否可以列出开始菜单,可能的方法是手机硬键盘的windows标记按钮),并没有涉及菜单的标 志。
因此,为了隐藏菜单,而且又为了不妨碍系统,就找到了SHFindMenuBar(hwnd)这个函数,它也是控制在本地句柄级别内的。
在用ShowWindow就可以隐藏找到的句柄。注意: SHFindMenuBar只是找出现有可以看到的菜单的句柄,即如果你隐藏了,SHFindMenuBar就找不到了,所以如果你要恢复菜单,那么请你在隐藏前,保存找到的菜单句柄。
但是实际过程中,你会发现,ShowWindow(SHFindMenuBar(hwnd), SW_HIDE)并没有彻底隐藏菜单栏,而是隐藏了你自己的菜单,也就是说如果你执行ShowWindow(SHFindMenuBar(hwnd), SW_HIDE)一次后,会看到屏幕仍旧有一个空的菜单栏,只是原先有字的菜单不见了。 这是为什么呢?
事实上,原因是,一个窗口在没有建立用户自定义菜单时,已经有了一个默认菜单
ShowWindow(SHFindMenuBar(hwnd), SW_HIDE)之后 你再去SHFindMenuBar(hwnd),又会得到一个句柄,你得再把它隐藏掉。当然,如果你没有构造自定义菜单,那只有一个默认菜单。
如果你还需要在退出全屏时,重新显示菜单,那要怎么办呢,以建立了自定义菜单为例,理论上来说,你得把刚才的两次SHFindMenuBar(hwnd)都保存句柄,然后依次ShowWindow(hmenu, SW_SHOW), hmenu有2个。
但是在实测过程中,我发现,没有必要显示默认的菜单栏,因为已经有自定义菜单栏覆盖在上面了。当然出于严谨的态度,我还是打算在最终版本中,将2个句柄都SW_SHOW。以免造成纰漏。
如果没有自定义菜单,只有默认菜单,那只要一次来回就行了。
第三点 注意窗口的移动
由于上述的隐藏只是隐藏,WM不会向积木一样因为缺少了窗口而自动调整,因此在隐藏后的地方,仍旧没有重绘,需要我们自己用
MoveWindow来重新调整窗口位置。
在全屏过程中:SetRect(&SCR_Rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));获得窗口的最大表现。
在逆全屏过程中:SystemParametersInfo(SPI_GETWORKAREA, 0, &WORK_Rect, 0);获取本来面目大小。
第四点 全屏不受干扰
也许,你已经很满意了,这样就可以隐藏界面上所有的乱七八糟的东西了。
但是你会不经意发现,当点击SIPB、或者按了下手机上的照相机按钮等离开窗口时的动作发生后,原先已经全屏的窗口再一次变成了不全屏,也就是在本贴开头的提问, 不过由于没有人回答这个问题,我不得不自己找。
在MFC的窗体类中加入,2个消息ON_WM_SETTINGCHANGE()、ON_WM_ACTIVATE()
并本窗体内重载CDialog的OnSettingChange、OnActivate方法。
将OnSettingChange方法置为空方法{}
ON_WM_SETTINGCHANGE()消息可以被触发如,点击SIPB时,因此当触发时,就不让它做任何事,这样点击SIPB就不会还原,估计CDialog的OnSettingChange方法内部具有还原全凭的代码。
但是这还不够,因为比如按了照相机按钮、短信按钮等,仍旧会让窗体的全屏失效,这时候ON_WM_ACTIVATE()消息就发挥了作用。
在重载的OnActivate方法中,再一次调用全屏代码,就能 即使窗体受到干扰,也能在干扰后“恢复”(其实就是再一次)全屏。
第五点 其他
剩下的就是如何有机的组合各种状态,比如我不隐藏“任务栏”,只隐藏菜单栏,那么窗体移动就要考虑位置问题,不能一味的往屏幕左上(0,0)移动,而是要往WorkArea的左上移动。等等的各类组合,就要自己灵活调整了。
ConnMgrQueryDetailedStatus 该函数返回存在连接的详细信息。
ConnMgrEnumDestinations 该函数枚举可用的网络连接。
ConnMgrConnectionStatus 该函数返回当前连接状态。